一、实现原理
当浏览器登录认证成功后,RememberMeService会加密一串Token传给浏览器,存入cookie中,再写入数据库,下一次浏览器访问时,RememberMeAuthenticationFilter就会读取cookie中的Token,由RememberMeService从数据库查找对应的Token来进行比较,相同则自动登录
二、实现代码
2.1、配置类:注入数据源,配置操作数据对象
注:如果没有创建表,第一次运行使用setCreateTableOnStartup这个方法自动创建表成功后,下一次运行就需要注销,否则运行创建相同的表会报错
//注入数据源
@Autowired
DataSource dataSource;
//配置操作数据的对象
@Bean
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//自动创建表 该代码在没有创建表的情况下只能运行一次,创建表后不能运行该行代码
//jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
2.2、配置类:配置自动登录
.and().rememberMe().tokenRepository(persistentTokenRepository()) //设置操作数据对象
.tokenValiditySeconds(60) //配置有效时长,单位为秒
.userDetailsService(userDetailsService) //设置使用userDetailsService底层操作数据库
2.3、配置类完整代码
包含一些其他功能设置
UserDetailsService实现类参考:https://blog.youkuaiyun.com/hjjjjjjj_/article/details/120235512
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
//注入数据源
@Autowired
DataSource dataSource;
//配置操作数据的对象
@Bean
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//自动创建表 该代码在没有创建表的情况下只能运行一次,创建表后不能运行该行代码
//jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
//配置操作数据的对象
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/*BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode = bCryptPasswordEncoder.encode("123456");
//如果没有设置roles,就会报错
auth.inMemoryAuthentication().withUser("lucy").password(encode).roles("admin");*/
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//注销
http.logout().logoutUrl("/logout").logoutSuccessUrl("/suss.html").permitAll();
//自定义403页面,没有权限,自动跳转的页面
http.exceptionHandling().accessDeniedPage("/unAuth.html");
http.formLogin() //自定义登录页面
.loginPage("/login.html") //登录页面设置
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/suss.html").permitAll() //登录成功后跳转路径,permitAll表示无条件进行访问
.and().authorizeRequests()
.mvcMatchers("/","/hello","/user/login").permitAll() //设置不需要认证可以直接访问的路径
//.mvcMatchers(("/index")).hasAnyRole("admin,aaa")
.anyRequest().authenticated()
//配置自动登录
.and().rememberMe().tokenRepository(persistentTokenRepository()) //设置操作数据对象
.tokenValiditySeconds(60) //配置有效时长,单位为秒
.userDetailsService(userDetailsService) //设置使用userDetailsService底层操作数据库
.and().csrf().disable(); //关闭csrf保护
}
//加密密码需要用到PasswordEncoder接口,需要设置PasswordEncoder实例化对象
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
2.4、设置登录页面
注:这里的记住我复选框的名字必须是remember-me,否则无法完成该功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<form action="/user/login" method="post">
用户名:<input type="text" name="username"/><br>
密码:<input type="password" name="password"/><br>
<input type="checkbox" name="remember-me"/>记住我<br>
<input type="submit" value="登录"/>
</form>
</body>
</html>
三、测试
先访问需要认证才能进入的页面,认证成功后,浏览器中可以查看到SpringSecurity发送过来的cookie,删除浏览器再打开同一个,访问需要认证才能进入的页面,此时不需要认证也可访问