anthony44 (3) [Avatar] Offline
#1
Hello

I add remember functionality within source code
1. Modify bean-security.xml

<security:http auto-config="true">
<security:form-login default-target-url="/home.html" />
<security:logout logout-success-url="/home.html" />
<security:access-denied-handler error-page="/accessdenied.html"/>
<security:remember-me services-ref="rememberMeServices" key="testKeyForBlog" />
</security:http>

<bean id="rememberMeServices" >
class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<property name="tokenRepository" ref="customTokenRepository" />
<property name="userDetailsService" ref="userDetailsService" />
<property name="key" value="testKeyForBlog" />
<property name="tokenValiditySeconds" value="864000" />
</bean>

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="authenticationProvider" />
</security:authentication-manager>

<bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService" />
</bean>

<bean id="userDetailsService" class="com.springinpractice.ch07.dao.hbn.HbnAccountDao" />

2. Create persistent_logins

create table persistent_logins (
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null
);

3. Create Object Token (package com.springinpractice.ch07.domain)

@Entity
@Table(name = "persistent_logins")
public class Token {

private String series;
private String username;
private String token;
private Date last_used;

public Token() {
}

public Token(PersistentRememberMeToken persistentRememberMeToken) {
this.username = persistentRememberMeToken.getUsername();
this.series = persistentRememberMeToken.getSeries();
this.last_used = persistentRememberMeToken.getDate();
this.token = persistentRememberMeToken.getTokenValue();
}

@Column(name = "username")
public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

@Id
@Column(name = "series")
public String getSeries() {
return series;
}

public void setSeries(String series) {
this.series = series;
}

@Column(name = "token")
public String getTokenValue() {
return token;
}

public void setTokenValue(String tokenValue) {
this.token = tokenValue;
}

@Column(name = "last_used")
public Date getDate() {
return last_used;
}

public void setDate(Date last_used) {
this.last_used = last_used;
}
}

4.DAO (package com.springinpractice.ch07.dao.hbn)

@Repository
@Transactional
public class HbnTokenDao {

@Resource
private SessionFactory sessionFactory;

public void createNewToken(Token token) {
sessionFactory.getCurrentSession().save(token);
}

public void updateToken(String series, String tokenValue, Date lastUsed) {

Token existingToken = (Token) sessionFactory.getCurrentSession().get(Token.class, series);
existingToken.setTokenValue(tokenValue);
existingToken.setDate(lastUsed);
sessionFactory.getCurrentSession().merge(existingToken);
}

public Token getTokenForSeries(String seriesId) {
Session mySession = sessionFactory.getCurrentSession();
System.out.println("mySession:"+mySession);
return (Token) sessionFactory.getCurrentSession().get(Token.class, seriesId);
}

public void removeUserTokens(final String username) {

Token token =
(Token) sessionFactory.getCurrentSession().createCriteria(Token.class)
.add(Restrictions.eq("username", username)).uniqueResult();
if (token != null) {
sessionFactory.getCurrentSession().delete(token);
}
}
}

5. finally, implementation remember service (package com.springinpractice.ch07.service.impl)

@Component
public class CustomTokenRepository implements PersistentTokenRepository {

@Autowired
private HbnTokenDao tokenDao;

@Override
public void createNewToken(PersistentRememberMeToken token) {
tokenDao.createNewToken(new Token(token));
}

@Override
public void updateToken(String series, String tokenValue, Date lastUsed) {
tokenDao.updateToken(series, tokenValue, lastUsed);
}

@Override
public PersistentRememberMeToken getTokenForSeries(String seriesId) {
System.out.println("seriesId:"+seriesId);
Token token = tokenDao.getTokenForSeries(seriesId);
if (token == null) {
return null;
}
System.out.println("Token:"+token.getUsername());
return new PersistentRememberMeToken(token.getUsername(),
token.getSeries(), token.getTokenValue(), token.getDate());
}

@Override
public void removeUserTokens(String username) {
tokenDao.removeUserTokens(username);
}
}


First, it works fine...SPRING_SECURITY_REMEMBER_ME_COOKIE cookie is created. When i restart my browser, the token is read, account too but i've an exception "java.lang.ClassCastException: com.opensymphony.sitemesh.webapp.ContentBufferingResponse cannot be cast to org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper"

So i decide to modify web.xml by calling spring before sitemesh filter. Now, rememberme authentification works but the default spring login form but the sitemesh template is not applied (spring call before sitemesh smilie ...)

Could you help me to restore the orginal login form with rememberme functionality

Cheers

Anthony

Architecture :
Eclipse 3.8
Tomcat 6.0
H2dbsql
willie.wheeler (110) [Avatar] Offline
#2
Re: Chapter 6: Spring security Rememberme and Sitemesh
Yeah, you are running into one of the challenges around using Spring Security with Sitemesh. Since they are both filter-driven, you have to decide which one you want to be out in front. If you put Sitemesh in front, then everything gets styled, but the Sitemesh decorators can't have Spring Security info in them (e.g. current principal's name). If on the other hand you put Spring Security in front, then your login form ends up without styles.

There are various hacky things you can do to sidestep this dilemma, such as styling your login form manually. I'd be interested to hear from others if there's a cleaner approach for this, short of abandoning Sitemesh altogether. (E.g. the issue doesn't come up with Apache Tiles because there's no filter.)