记住我功能的基本原理
用户发送请求到UsernamePasswordAuthenticationFilter,当用户认证成功以后,会调一个RemeberMeService这样一个服务。这个服务里面有一个TokenRepository,会生成一个Token,将这个Token写入到浏览器的Cookie里面,同时TokenRepository把生成的Token写入到数据库里面(还有用户名)。过了一天用户来访问系统 就不需要登陆了,直接访问某一个受保护的服务,这个请求在经过过滤器链的时候会经过RemberMeAuenticationFilter(读取Cookie中的Token)给RemberMeService,RemberMeService会根据Token到数据库里面去查。如果有记录,就会把Username用户名取出来,取出来之后会调用UserDetailsService,获取用户信息,然后把用户信息放入到SecurityContext里面。
RemberMeAuenticationFilter位置:
实现:
页面:
安全配置类:
/**
* 安全配置类
* @author zhailiang
*
*/
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityProperties securityProperties;
@Autowired
private AuthenticationSuccessHandler imoocAuthenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler imoocAuthenctiationFailureHandler;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//记住我的主要操作配置
@Autowired
private DataSource dataSource;
@Autowired
private UserDetailsService userDetailsService;
//记住我的主要操作配置
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
// tokenRepository.setCreateTableOnStartup(true);
return tokenRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//验证码的配置
ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
validateCodeFilter.setAuthenticationFailureHandler(imoocAuthenctiationFailureHandler);
validateCodeFilter.setSecurityProperties(securityProperties);
validateCodeFilter.afterPropertiesSet();
//将验证码的过滤器放在登录验证过滤器之前
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
.formLogin()
.loginPage("/authentication/require")
.loginProcessingUrl("/authentication/form")
.successHandler(imoocAuthenticationSuccessHandler)//登录成功的处理
.failureHandler(imoocAuthenctiationFailureHandler)//登录失败的处理
.and()
.rememberMe()//记住我的操作
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
.userDetailsService(userDetailsService)
.and()
.authorizeRequests()
.antMatchers("/authentication/require",
securityProperties.getBrowser().getLoginPage(),
"/code/image").permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().disable();
}
}
BrowserProperties:
public class BrowserProperties {
private String loginPage = "/imooc-signIn.html";
private LoginType loginType = LoginType.JSON;
//记住密码的时间
private int rememberMeSeconds = 3600;
public String getLoginPage() {
return loginPage;
}
public void setLoginPage(String loginPage) {
this.loginPage = loginPage;
}
public LoginType getLoginType() {
return loginType;
}
public void setLoginType(LoginType loginType) {
this.loginType = loginType;
}
public int getRememberMeSeconds() {
return rememberMeSeconds;
}
public void setRememberMeSeconds(int rememberMeSeconds) {
this.rememberMeSeconds = rememberMeSeconds;
}
}