Spring Security 提供了Remember-me机制用来实现记录用户的登录状态。方便用户下
次自动登录。Spring Security 对此操作提供了必要的钩子,remember-me有两个固定的实现
一个是使用把用户登录信息加密以cookie的方式保存到客户端。一是用户可以把用户信息
持久化到服务端的数据库中。
注意:这两种实现都必须有一个 UserDetailsService实现。如果你使用一个没有使用
UserDetailsService的验证提供者,Remember-me将不会工作,除非你在应用的上下文中
有一个UserDetailsService对象。
一、基本的Hash保存到客户端的Cookie中。
直接在命名空间<http>中加入<remember-me />元素,就可以使用本方法。但要注意的
是在你的。此时系统会自动为你生成UserDetailsService对象(如果你在配置文件中定义了此
对象必须在<remember-me />使用user-service-ref指定)。本策略使用的为
org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices
此策略会在客户端生成一个名称为SPRING_SECURITY_REMEMBER_ME_COOKIE,值进
行加密后的Cookie。
二、持久化到服务器端的服务器中
如果想使用本策略,你需要在命名空间的配置中提供一个datasource引用:
<http>
....
<remember-me data-source-ref="someDataSource" />
</http>
数据库中还必须包含一个名为persistent_logins的表,表结构使用一下SQL语句创建(或者是等价的):
create table persistent_logins (
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null)
由于以上两种策略对应的实现类都的父类(org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices)实现了LogoutHandler接口。
在AbstractRememberMeServices类中的 logout(...)方法中清楚了Cookie。如下所示:
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
if (logger.isDebugEnabled()) {
logger.debug( "Logout of user "
+ (authentication == null ? "Unknown" : authentication.getName()));
}
cancelCookie(request, response);
}
...
/**
* Sets a "cancel cookie" (with maxAge = 0) on the response to disable persistent logins.
*
* @param request
* @param response
*/
protected void cancelCookie(HttpServletRequest request, HttpServletResponse response) {
logger.debug("Cancelling cookie");
Cookie cookie = new Cookie(cookieName, null);
cookie.setMaxAge(0);
cookie.setPath(getCookiePath(request));
response.addCookie(cookie);
}
......
如果想在用户安全退出后不删除Cookie, 可以自己实现类,实现类可以继承org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices 或
org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices。在自定义类中只重写org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices
类中的logout(...)方法即可。(但是这样 就失去了安全退出的意义了。哈哈)