Yesterday I implemented my login form using Spring Security. One thing I added was the ability to check a checkbox so a user would stay logged in for a certain period even if he closes his browser. You’re probably familiar with the idea.
In Spring this is done using the RememberMeAuthenticationFilter. And when you use the basic implementation, like I did, it’s based on a cookie and an in memory ‘cache’ for holding the key value in the cookie that’s linked to the user. For now, that suites my needs.
My applicationContext-security.xml looks like this (btw, I’m using Spring 3.0.0.RELEASE):
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http>
<intercept-url pattern="/static/**" filters="none"/>
<intercept-url pattern="/favicon.ico" filters="none"/>
<intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="ROLE_USER"/>
<form-login always-use-default-target='false' login-processing-url="/login" default-target-url="/" authentication-failure-url="/" />
<remember-me/>
<logout logout-url="/logout"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN"/>
<user name="user" password="user" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
<global-method-security secured-annotations="enabled" jsr250-annotations="enabled"/>
</beans:beans>
As you can see, I didn’t yet setup my authentication provide as it should, but that’s OK for now. The important thing is the <remember-me> tag. That’s all it takes to implement a basic Remember Me implementation. Additionally, as one can stay logged in even after closing his browser, you need to provide some way to logout. So I putted the <logout> tag in as well.
Now, I’m using Velocity as my render engine. When a user is logged in, I don’t want to show any longer the login form, but some message like ‘welcome user x – log out’. I started using the variables that are exposed on the session in my velocity templates. To be able to do that, I had to expose my session variables to my model:
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
<property name="exposeSessionAttributes" value="true"/>
</bean>
So, that lets me write this in my velocity template:
<span>#springMessage('welcome') $SPRING_SECURITY_CONTEXT.authentication.getName().</span>
The problem with that is that we can’t rely on the session as we don’t know their is actually a session created and secondly, if the SecurityContext is set on the session. Logging in into the application using the Remember Me logic, this looks not be the case. The reasoning behind it is that the session is only used for holding status between different requests, not for rendering data to the view. The user info will off course be put on the session, but in our case, it happens too late in the process.
So, how do we solve this ?
Well, the solution appears to be easy (once you know it
). We adapt our view resolver like this:
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
<property name="exposeSessionAttributes" value="true"/>
<property name="attributes">
<map>
<entry key="authentication">
<bean class="com.idevelop.kizhi.web.util.AuthenticatedUserDetails"/>
</entry>
</map>
</property>
</bean>
Meaning that we add a bean AuthenticatedUserDetails to our model and it will be accessible with the key authentication. The AuthenticatedUserDetails class is nothing more than a class that accesses info from the SecurityContext in a nice manner for our velocity template. It looks like this:
public class AuthenticatedUserDetails {
/**
* Get the user name of the logged in user.
*
* @return the user name of the user
*/
public static String getPrincipal() {
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (obj instanceof UserDetails) {
return ((UserDetails) obj).getUsername();
} else {
return null;
}
}
}
And now in our velocity template, we can write the following as we exposed our bean to our model:
<span>#springMessage('welcome') $authentication.principal.</span>
For completeness, this is how the login form looks like:
#* @vtlvariable name="authentication" type="com.idevelop.kizhi.web.util.AuthenticatedUserDetails" *#
#* @vtlvariable name="SPRING_SECURITY_LAST_EXCEPTION" type="org.springframework.security.authentication.BadCredentialsException" *#
#* @vtlvariable name="SPRING_SECURITY_LAST_USERNAME" type="java.lang.String" *#
<div class="login">
#if(!$authentication.principal)
<form id="logInForm" method="POST" action="/login">
<div class="header"><p>#springMessage('loginHeader').</p></div>
#if ($SPRING_SECURITY_LAST_EXCEPTION)
<div class="error"><p>#springMessage($SPRING_SECURITY_LAST_EXCEPTION.message)</p></div>
#end
<div class="fields">
<p>
<label for="j_username" class="formLabel">
#springMessage('userName'):
</label>
<input class="text medium-field" type="text" id="j_username" name="j_username" tabindex="1"
value="$!SPRING_SECURITY_LAST_USERNAME" size="30"/>
<br/>
</p>
<p>
<label for="j_password" class="formLabel">
#springMessage('password'):
</label>
<input type="password" name="j_password" id="j_password" tabindex="2" size="30"/>
<br/>
</p>
<p>
<label for="_spring_security_remember_me" class="checkboxLabel">
<input type='checkbox' name='_spring_security_remember_me' id="_spring_security_remember_me"
tabindex="3" value="true"/>
#springMessage('rememberMe')
</label>
<br/>
</p>
</div>
<div class="buttons">
<p>
<input id="login" class="button" type="submit" value="#springMessage('login')" tabindex="4"/>
</p>
</div>
</form>
<div class="forgotPassword">
<a href="#" target="_parent">#springMessage('forgotPassword')</a>
</div>
#end
</div>
And that’s how it’s done. Once you know it, it’s peanuts, but it took me quite some googling before finding this out. I hope this post wins you some time.
Tags: remember me, Spring Security, Velocity
i want to develope the login form using spring tags
using
Please help me
how to devlop that