Last updated by
4 years ago
Page: AcegiSecurity Plugin - Ajax Authentication, Version:5
The typical pattern of using web site authentication to access restricted pages involves intercepting access requests for secure pages, redirecting to a login page (possibly off-site) and redirecting back to the originally-requested page after a successful login. Each page can also have a login link to allow explicit logins at any time.
Another option is to also have a login link on each page and use Ajax and DHTML to present a login form within the current page in a popup. The form submits the authentication request via Ajax and displays success or error messages as appropriate.
The Spring Security plugin has support for Ajax logins but you'll need to create your own GSP code. There are only a few necessary changes, and of course the sample code here is pretty basic so you should enhance it for your needs.The approach I'll show here involves editing your template page(s) to show "You're logged in as ..." text if logged in and a login link if not, along with a hidden login form that's shown using DHTML.Here's the updated grails-app/views/layouts/main.gsp:
The changes to note here include:
The important aspects of this code are:
Another option is to also have a login link on each page and use Ajax and DHTML to present a login form within the current page in a popup. The form submits the authentication request via Ajax and displays success or error messages as appropriate.
The Spring Security plugin has support for Ajax logins but you'll need to create your own GSP code. There are only a few necessary changes, and of course the sample code here is pretty basic so you should enhance it for your needs.The approach I'll show here involves editing your template page(s) to show "You're logged in as ..." text if logged in and a login link if not, along with a hidden login form that's shown using DHTML.Here's the updated grails-app/views/layouts/main.gsp:
<html> <head><title><g:layoutTitle default='Grails' /></title> <link rel='stylesheet' href='${createLinkTo(dir:'css',file:'main.css')}' /> <link rel='shortcut icon' type='image/x-icon' href='${createLinkTo(dir:'images',file:'favicon.ico')}' /><g:layoutHead /><g:javascript library='application' /> <g:javascript library='scriptaculous' /></head><body><g:render template='/includes/ajaxLogin'/><div id='spinner' class='spinner' style='display:none;'> <img src='${createLinkTo(dir:'images',file:'spinner.gif')}' alt='Spinner' /> </div><div class='logo'> <img src='${createLinkTo(dir:'images',file:'grails_logo.jpg')}' alt='Grails' /> <span id='loginLink' style='position: relative; margin-right: 30px; float: right; top: -60px'> <g:isLoggedIn> Logged in as <g:loggedInUsername/> (<g:link controller='logout'>Logout</g:link>) </g:isLoggedIn> <g:isNotLoggedIn> <a href='#' onclick='showLogin(); return false;'>Login</a> </g:isNotLoggedIn> </span></div><g:layoutBody/></body> </html>
- the scriptaculous library is included to have support for hiding and showing the login form
- there's an include of the template '/includes/ajaxLogin' (see the code below)
- and finally there's a <span> positioned in the top-right which shows the username and a logout link when logged in, and a login link otherwise
<style type='text/css' media='screen'>
#ajaxLogin {
margin: 15px 0px; padding: 0px;
text-align: center;
display: none;
position: absolute;
}
#ajaxLogin .inner {
width: 260px;
margin:0px auto;
text-align:left;
padding:10px;
border-top:1px dashed #499ede;
border-bottom:1px dashed #499ede;
background-color:#EEF;
}
#ajaxLogin .inner .fheader {
padding:4px;margin:3px 0px 3px 0;color:#2e3741;font-size:14px;font-weight:bold;
}
#ajaxLogin .inner .cssform p{
clear: left;
margin: 0;
padding: 5px 0 8px 0;
padding-left: 105px;
border-top: 1px dashed gray;
margin-bottom: 10px;
height: 1%;
}
#ajaxLogin .inner .cssform input[type='text']{
width: 120px;
}
#ajaxLogin .inner .cssform label{
font-weight: bold;
float: left;
margin-left: -105px;
width: 100px;
}
#ajaxLogin .inner .login_message {color:red;}
#ajaxLogin .inner .text_ {width:120px;}
#ajaxLogin .inner .chk {height:12px;}
.errorMessage { color: red; }
</style><div id='ajaxLogin'>
<div class='inner'>
<div class='fheader'>Please Login..</div>
<form action='${request.contextPath}/j_spring_security_check' method='POST'
id='ajaxLoginForm' name='ajaxLoginForm' class='cssform'>
<p>
<label for='j_username'>Login ID</label>
<input type='text' class='text_' name='j_username' value='' />
</p>
<p>
<label for='j_password'>Password</label>
<input type='password' class='text_' name='j_password' value='' />
</p>
<p>
<label for='j_password'>Remember me</label>
<input type='checkbox' class='chk' name='_spring_security_remember_me'>
</p>
<p>
<a href='javascript:void(0)' onclick='authAjax(); return false;'>Login</a>
</p>
</form>
</div>
<div style='display: none; text-align: left;' id='loginMessage'></div>
</div><script type='text/javascript'>// center the form
$('ajaxLogin').style.left = ((document.viewport.getWidth() - 300) / 2) + 'px';
$('ajaxLogin').style.top = ((document.viewport.getHeight() - 300) / 2) + 'px';function showLogin() {
$('ajaxLogin').style.display = 'block';
}function onSuccessfulLogin() {
Element.hide('ajaxLogin');
Element.hide('loginLink');
}function authAjax() {
Element.update('loginMessage', 'Sending request ...');
Element.show('loginMessage'); var form = document.ajaxLoginForm;
var params = Form.serialize(form) + '&spring-security-redirect=/login/ajaxSuccess';
Form.disable(form);
new Ajax.Request(form.action, {
method: 'POST',
postBody: params,
onSuccess: function(response) {
var responseText = response.responseText || '[]';
var json = responseText.evalJSON();
if (json.success) {
onSuccessfulLogin();
}
else if (json.error) {
Element.update('loginMessage', "<span class='errorMessage'>" + json.error + '</error>');
Form.enable(document.ajaxLoginForm);
}
else {
Element.update('loginMessage', responseText);
Form.enable(document.ajaxLoginForm);
}
}
});
}
</script>- the form posts to the same url as the regular form, 'j_spring_security_check'; in fact the form is identical including the Remember Me checkbox, except that the submit button has been replaced with a hyperlink
- the Javascript function that submits the form appends a parameter 'spring-security-redirect'. This is new as of Spring Security 2.0. If this parameter is present, it overrides the default behavior of sending a server-side redirect to the default post-login page, but we need to render JSON or XML as the Ajax response instead