How to customize Spring Security Shiro Grails plugin Login Logout functionality? - grails

This seems like something that should be pretty easy, but I am unable to customize the Login (login/authenticate) and Logout functionality of spring-security-shrio that is pre-built.
I would like to do things like add a login counter, or login log so when a user logs in I log who they are and additional information like an ip address.
Also, I went to the source and found the LoginController, copied that but noticed that there is no authenticate method within that controller.
I am upgrading an application from Grails version 2.4.4 to Grails 3+. Where is the code that is generated? Any guidance would be most appreciated.

Not Shiro specific but you can add a login directory to views then add your own auth.gsp to handle logging in.
Note that a number of the parameter names changed from Grails 2 to 3 e.g. j_username to username see here.
Here's a bootstrap styled one I converted from a Grails 2 to 3 app recently:
<html>
<head>
<meta name='layout' content='main'/>
<title><g:message code="springSecurity.login.title"/></title>
</head>
<body>
<div id='login' class="maincontentdiv">
<g:render template="/templates/alerts"/>
<form action='${postUrl}' method='POST' id='loginForm' class='form-horizontal' autocomplete='off'>
<fieldset>
<legend><g:message code="springSecurity.login.header"/></legend>
<div class="form-group">
<label class="col-md-4 control-label" for="username">
<g:message code="springSecurity.login.username.label" default="Username" />
<span class="required-indicator">*</span>
</label>
<div class="col-md-4">
<input type='text' class='form-control' name='username' id='username'/>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="password">
<g:message code="springSecurity.login.password.label" default="Password" />
<span class="required-indicator">*</span>
</label>
<div class="col-md-4">
<input type='password' class='form-control' name='password' id='password'/>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="submit"></label>
<div class="col-md-4">
<input type='submit' id="submit" class='btn btn-primary' value='${message(code: "springSecurity.login.button")}'/>
</div>
</div>
</fieldset>
</form>
</div>
<script type='text/javascript'>
<!--
(function() {
document.forms['loginForm'].elements['username'].focus();
})();
// -->
</script>
</body>
</html>

Related

Why "href" and "th:href" exist at the same time?

I am reading a page using Thymeleaf.
In "Edit page", there is a "Back" button for going back to "User List Page". The strange thing for me is this button has "href" and "th:href" at the same time.
image detail of the button
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>user</title>
<link rel="stylesheet" th:href="#{/css/bootstrap.css}"></link>
</head>
<body class="container">
<br/>
<h1>修改用户</h1>
<br/><br/>
<div class="with:80%">
<form class="form-horizontal" th:action="#{/edit}" th:object="${user}" method="post">
<input type="hidden" name="id" th:value="*{id}" />
<div class="form-group">
<label for="userName" class="col-sm-2 control-label">userName</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="userName" id="userName" th:value="*{userName}" placeholder="userName"/>
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label" >Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" name="password" id="password" th:value="*{password}" placeholder="Password"/>
</div>
</div>
<div class="form-group">
<label for="age" class="col-sm-2 control-label">age</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="age" id="age" th:value="*{age}" placeholder="age"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" value="Submit" class="btn btn-info" />
Back
</div>
</div>
</form>
</div>
</body>
</html>
It is obvious that "th:href" is for going back. Is there any opition on what is the function of the atrribute "href"?
ThymeLeaf is designed to use the same file for both as prototype you can view in your browser as well as a working template file. What this means in practice is that if you want, you can open the template file in a browser without actually running it and it still looks okay. For example, in this code:
Back
If you open the file directly in a browser, the browser will ignore the th:href (because it doesn't know what to do with it) and instead use href="/toAdd". However, when you run it through the templating engine on a server, href="/toAdd" is replaced with the result of the dynamic expression th:href="#{/list}".
This is more easily shown with a table. Like this:
<table>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>IN STOCK</th>
</tr>
<tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
</table>
When you open that in a browser, you'll see a table with a single row (Onions, 2.41, yes). But when you run it through the server, the actual content of the table is replaced with whatever data exists in the ${prods} variable.

Rails devise two separate registration forms

I am building a Doctor booking platform where there's a patient and a doctor.
I currently have standard devise setup with one user model and one signup form, I want to have to separate forms one for patient where I will pass params role of patient and a doctor form with params of doctor role so I can assign roles from the controller or the model.
The forms will be quite the same only for doctor I will require some extra fields.
Also my doctor as it belongs to a user will have the ability to book an appointment with other doctors, is it a good practice to use boolean to define whether it's a doctor or not or use roles with enum.
I need help please
What about hidden_field_tag, did you have tried anything or want to clear concept? You can do this using hidden_field_tag like if you create those form using bootstrap tab like this
$('#myTabs a').click(function (e) {
e.preventDefault()
$(this).tab('show')
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<div>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">Doctor</li>
<li role="presentation">Patient</li>
</ul>
<h2>Just example form</h2>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="home">
<h2>Doctor?</h2>
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
<div role="tabpanel" class="tab-pane" id="profile">
<h2>Patient?</h2>
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
in the form, you can just use a hidden field like when form for doctor
<%= f.hidden_field :role, value: "doctor" %>
and when form for Patient
<%= f.hidden_field :role, value: "patient" %>
and permit their role in the application_controller
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :role])
end
I thing it will help.

Grails spring-security-ldap plugin change user password for AD

I have a grails application (2.5.0) using Spring security and authenticating with the spring-security-ldap plugin (2.0-RC2) against a windows AD domain.
This works very well to authenticate but now I have the requirement to allow the user to change their password (in fact to require it!).
Despite searching through the documentation, Reading the code and searching with google All I can find is references to LdapUserDetailsManager.changePassword but I cannot find a single example of how to use this.
I find in the plugin
public class GrailsLdapUserDetailsManager extends LdapUserDetailsManager
implements GrailsUserDetailsService {....
but this does not have the changePassword and I do not understand how to call it if it did.
I have looked through all the StackOverflow questions such as
how to change password using spring ldap and spring security
but the answers appear to be written in some other language and talk about things I do not have like xml files.
Can someone tell me, preferably with an understandable example how I can implement a change Password feature in Grails against an ldap AD source in conjunction with the grails spring-security-ldap plugin? Authentication without the ability to manage changing the passwords is just wrong!
You can make use of the ldapUserDetailsManager by injecting into your controller e.g.
gsp:
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main">
<title><g:message code="menu.item.change.password" /></title>
</head>
<body>
<div class="maincontentdiv" role="main">
<div class="alert alert-info alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
flash.changePasswordMessage
</div>
<h3><g:message code="menu.item.change.password" /></h3>
<g:form class="form-horizontal">
<div class="form-group">
<label class="col-md-4 control-label" for="currentPassword">Current password</label>
<div class="col-md-4">
<g:field type="password" name="currentPassword" class="form-control" required="true" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="newPassword">New password</label>
<div class="col-md-4">
<g:field type="password" name="newPassword" class="form-control" pattern=".{6,15}" required title="Password must be a minimum of 6 and a maximum of to 10 characters" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="confirmNewPassword">Confirm new password</label>
<div class="col-md-4">
<g:field type="password" name="confirmNewPassword" class="form-control" pattern=".{6,15}" required title="Password must be a minimum of 6 and a maximum of to 10 characters" />
</div>
</div>
<g:render template="/templates/generic_submit_button" model="[btnname: 'changePassword', btntxt: 'Change password']" />
</g:form>
</div>
</body>
</html>
Controller:
class ChangePasswordController {
def ldapUserDetailsManager
def index() {
if ( params.changePassword ) {
try {
if ( params.newPassword.equals( params.confirmNewPassword ) ) {
ldapUserDetailsManager.changePassword( params.currentPassword, params.newPassword )
}
else {
throw new InvalidParameterException( 'Please ensure the new password and confirm new password fields match' )
}
}
catch( all ) {
flash.changePasswordMessage= all.message
}
}
}
}

When using Angular.js, how to retain form data after submit?

I have used the basic angular script which update what ever you type in the input field on any element we specify, real time...
<!doctype html>
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
</head>
<body>
<div>
<label>Name:</label>
<input type="text" ng-model="yourName" placeholder="Enter a name here">
<hr>
<h1>Hello {{yourName}}!</h1>
</div>
</body>
</html>
Im new to Angular. I used this on may rails app. But the problem is, the field I used ng-model will reset its valu after submit. Even setting the 'value' attribute won't work. How can I fix this?
Exact code generated from my rails application :
<form accept-charset="UTF-8" action="/members" class="custom" id="new_member" method="post">
<div class="row collapse text-field">
<div class="small-4 columns">
<h3>Add Member : </h3>
</div>
<div class="small-6 columns left inline">
<h3 class="subheader inline"> {{newEntry.name}}</h3>
</div>
</div>
<div class="row collapse text-field">
<div class="small-3 columns">
<label class="prefix" for="member_name">Full Name</label>
</div>
<div class="small-7 columns left">
<input class="input" id="member_name" name="member[name]" ng-model="newEntry.name" type="text" value="gj" />
</div>
</div>
<div class="row collapse text-field">
<div class="small-3 columns">
<label class="prefix" for="member_address">Address</label>
</div>
<div class="small-9 columns">
<textarea class="input" height="115" id="member_address" name="member[address]">
</textarea>
</div>
</div>
<div class="row">
<div class="small-9 columns" ><input class="button radius" name="commit" type="submit" value="Add Member" /></div>
</div>
</form>
Note : I haven't used an ng-controller. Im new to Angular. If its required, please tell me how to convert the above to the controller. I can get the value of the field and send it back to the form in rails. Its there in a variable. But Angular keeps wiping it!
Note2 : This problem persist only for the input field I used angular-model.. All the other fields retained the data!
Ok this is not the best solution but you could do this:
<input type="text" ng-init="yourName = 'Your Value Goes Here'" ng-model="yourName" placeholder="Enter a name here">
ng-init directives are run when the app intialises, so your value will be assigned to angular's internal "yourName" model and be updated in the view accordingly.
That would solve your problem but its not the best way. Hopefully that will get you going for now - I'll try and post a more "ideal" solution shortly.

how to put login form # center of screen

I am developing MVC 3 application along with it I am using bootstrap for design.
I have created the log in form.
I am trying to set it at center position of the screen but some how its not working.
This is my code.
#using (Html.BeginForm("LoginUser","Login",FormMethod.Post))
{
<div class="container-fluid" style="padding-left:0px; margin-top:165px; margin-left:140px;">
<div class="row-fluid">
<div class="span12 roundedDiv offset4" style="width:400px; height:250px;">
...
...
...
Controls...
....
....
</div>
</div>
</div>
}
what to do ?
Margin auto does this for you, without having to use <center>.
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<style type="text/css">
#loginBox {
margin: 20% auto;
width: 200px;
}
</style>
</head>
<body>
<form action="index.php" method="POST" id="loginBox">
<input type="text" name="user" placeholder="Username" autocapitalize="off" /><br />
<input type="password" name="pass" placeholder="Password" /><br />
<input type="checkbox" name="remember"> Remember Me<br />
<input type="submit" value="Log In" name="login" />
</form>
</body>
</html>
I would advise against usage of margins for the horizontal alignment. Try something like this:
<div class="container-fluid">
<div style="margin-top:20px;" class="row-fluid">
<div class="offset4 span4 well">
<h1>Login page</h1>
<form method="POST">
<label>Login:
<input type="text" placeholder="Enter your login" name="username" autofocus class="span12">
</label>
<label>Password:
<input type="password" placeholder="Enter your password" name="password" class="span12">
</label>
<hr>
<div class="btn-toolbar">
<button type="submit" class="btn btn-info">Log in</button>Sign in with Google
</div>
</form>
</div>
</div>
This is code I used to build a simple login form.
Since you're using fluid container hence responsive design I'd recommend to avoid using hardcoded values like 400 px. Instead you can set it width by applying span class like:
<div class="row-fluid">
<div class="offset3 span6">
It gives you login form width of 6 rows and 3 rows offset on the left and right (12 rows is default bootstrap grid).

Resources