文章目录
原理
实现
登录页面添加记住我checkbox
<tr>
<td colspan='2'><input name="remember-me" type="checkbox" value="true" />记住我</td>
</tr>
注意 name=“remember-me” 是固定的
BrowserSecurityConfig 中初始化 PersistentTokenRepository
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
································
@Autowired
private DataSource dataSource;
······························
@Bean
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
//tokenRepository.setCreateTableOnStartup(true);
//启动时建立这张表persistent_logins,也可以吧创建表语句拿去手动执行
//只能执行一次,第二次需要关掉,否则报错MySQLSyntaxErrorException: Table 'persistent_logins' already exists
return tokenRepository;
}
································
其中DataSource为demo application中配置的数据源
BrowserProperties 加入记住时间属性
public class BrowserProperties {
·····················
private int rememberMeSecodes = 3600;//秒
························
BrowserSecurityConfig configure配置
首先引入UserDetailsService
@Qualifier("myUserDetailsService")
@Autowired
private UserDetailsService userDetailsService;//也要引入userDetailsService
config方法
@Override
protected void configure(HttpSecurity http) throws Exception {
//http.formLogin() //指定身份认证的方式为表单登录
//http.httpBasic()
ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
validateCodeFilter.setAuthenticationFailureHandler(whaleAuthenctiationFailureHandler);//设置错误过滤器
validateCodeFilter.setSecurityProperties(securityProperties);
validateCodeFilter.afterPropertiesSet();
http.addFilterBefore(validateCodeFilter,UsernamePasswordAuthenticationFilter.class)
.formLogin()
// .loginPage("/signIn.html") //指定登录页面的url
// .loginPage("/anthentication/require") //指定登录页面的url
.loginPage(securityProperties.getBrowser().getLoginPage()) //指定登录页面的url
.loginProcessingUrl("/authentication/form")
.successHandler(whaleAuthenticationSuccessHandler)
.failureHandler(whaleAuthenctiationFailureHandler)
.permitAll()
.and()
.rememberMe()
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSecodes())
.userDetailsService(userDetailsService)
.and()
.authorizeRequests() //对请求授权
// .antMatchers("/signIn.html","/code/image").permitAll() //加一个匹配器 对匹配的路径不进行身份认证
.antMatchers(securityProperties.getBrowser().getLoginPage(),"/code/image").permitAll() //加一个匹配器 对匹配的路径不进行身份认证
.anyRequest() //任何请求
.authenticated() //安全认证
.and()
.cors().disable().csrf().disable();// 禁用跨站攻击
// 默认都会产生一个hiden标签 里面有安全相关的验证 防止请求伪造 这边我们暂时不需要 可禁用掉
//任何请求都必须经过表单验证才能进行访问
/* http.csrf().disable().cors().disable().headers().disable()
.authorizeRequests()
.antMatchers("/signIn.html").permitAll() // 配置不需要身份认证的请求地址
.anyRequest().authenticated() // 其他所有访问路径需要身份认证
.and()
.formLogin()
.loginPage("/signIn.html") // 指定登录请求地址
.loginProcessingUrl("/authentication/form")
.permitAll();
*/
}
上一节的错误 启动报错
如果demo中的application中注释掉
#whale.security.code.image.url = /user,/user/*
configurls会为null,直接循环会报错,应该先判空,,否则系统启动报错 控制台打印如下错误信息
2019-05-17 08:40:23.998 WARN 5808 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.NullPointerException
测试
登录成功后,重新启动服务
说明登录信息是保存到数据库的
再看下数据库
AbstractAuthenticationProcessingFilter
class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
1创建新token放到数据库中
2将token写入浏览器中
RememberMeAuthenticationFilter
PersistentTokenBasedRememberMeServices
最后又回到userdetailservice