记住我功能原理:
项目中记住我配置:
//记住我配置,如果想在'记住我'登录时记录日志,可以注册一个InteractiveAuthenticationSuccessEvent事件的监听器
http.rememberMe()
.tokenRepository(persistentTokenRepository())//保存方式
//国企时间 .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
.userDetailsService(userDetailsService)//认证服务
/**
* 记住我功能的token存取器配置
* @return
*/
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
//自动创建表
// tokenRepository.setCreateTableOnStartup(true);
return tokenRepository;
}
JdbcTokenRepositoryImpl:用于rememberme功能数据存储
public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements
PersistentTokenRepository {
// ~ Static fields/initializers
// =====================================================================================
/** Default SQL for creating the database table to store the tokens */
public static final String CREATE_TABLE_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)";
/** The default SQL used by the <tt>getTokenBySeries</tt> query */
public static final String DEF_TOKEN_BY_SERIES_SQL = "select username,series,token,last_used from persistent_logins where series = ?";
/** The default SQL used by <tt>createNewToken</tt> */
public static final String DEF_INSERT_TOKEN_SQL = "insert into persistent_logins (username, series, token, last_used) values(?,?,?,?)";
/** The default SQL used by <tt>updateToken</tt> */
public static final String DEF_UPDATE_TOKEN_SQL = "update persistent_logins set token = ?, last_used = ? where series = ?";
/** The default SQL used by <tt>removeUserTokens</tt> */
public static final String DEF_REMOVE_USER_TOKENS_SQL = "delete from persistent_logins where username = ?";
。。。。。。。。。。。。。。。。。。。。。。。。。
sql:
CREATE TABLE `persistent_logins` (
`username` varchar(64) NOT NULL,
`series` varchar(64) NOT NULL,
`token` varchar(64) NOT NULL,
`last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
步骤说明:
表单登陆页面存在:
<input name="remember-me" type="checkbox" value="true" />记住我</td>
在登陆成功调用登陆成功处理的时候会先调用rememberMeServices的loginSuccess方法。
AbstractAuthenticationProcessingFilter:
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: "
+ authResult);
}
SecurityContextHolder.getContext().setAuthentication(authResult);
//记住我操作
rememberMeServices.loginSuccess(request, response, authResult);
// Fire event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
authResult, this.getClass()));
}
successHandler.onAuthenticationSuccess(request, response, authResult);
}
PersistentTokenBasedRememberMeServices:
protected void onLoginSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication successfulAuthentication) {
String username = successfulAuthentication.getName();
logger.debug("Creating new persistent login for user " + username);
PersistentRememberMeToken persistentToken = new PersistentRememberMeToken(
username, generateSeriesData(), generateTokenData(), new Date());
try {
//创建表结构 并且将数据存储在数据库中
tokenRepository.createNewToken(persistentToken);
//添加cookie
addCookie(persistentToken, request, response);
}
catch (Exception e) {
logger.error("Failed to save persistent token ", e);
}
}
登陆成功。
下一次请求过来。先进入RememberMeAuthenticationFilter拦截器中,从请求里面拿去cookie中的数据,然后去数据中进行查找相应用户的数据,
RememberMeAuthenticationFilter:
PersistentTokenBasedRememberMeServices:
之后又进入了 RememberMeAuthenticationFilter。