SpringSecurity-记得我

原理

IMG_256

在用户发送认证请求之后,或调用我们之前说过的usernamePasswordAuthenticationFilter这个过滤器,认证成功之后会调用一个RemeberMeService服务;负责针对每一用户生成一个Token,然后将token写入到浏览器的Cookie里面,同时会使用:TokenRepository将这个token写入数据库中。将Token写入数据库时候,同时会把用户认证成功的用户名一并写入数据库(此时用户名和token是一一对应的)中因为我们是在用户认证成功之后做的,所以会将用户信息写入,下次用户访问的时候就不需要再次登录了。当用户下次请求的时候会经过过滤器链中的RemeberMeAuthenticationFilter(这个过滤器作用就是读取cookie中token)然后交给RemeberMeService,RemeberMeService通过TokenRepository到数据库去查询这个Token数据库里面有没有记录。如果有记录就去除用户名,取出用户名之后,就会去调用UserDetailsService,获取用户信息,然后把获取的当前用户信息放到SecurityContext里面。这样就把用户登录上了。

RemeberMeAuthenticationFilter在我们的过滤器链中绿色过滤器中,他是在倒数第二个位置。前面是其他的认证,其他的认证都没法认证用户信息的时候RemeberMeAuthenticationFilter尝试去做认证。

IMG_256

实现

前端

IMG_256

配置TokenRepository

配置TokenRepository读取数据库,SecurityConfig类中配置

BrowserSecurityConfig类中

  1. 配置PersistentTokenRepository 读写数据库
  2. 配置token过期的秒数
  3. 验证token,配置UserDetailsService的实现类
复制代码
@Configuration
public class BrowserSecurityConfigOld extends WebSecurityConfigurerAdapter {

    //security配置类
    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    @Autowired
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Autowired
    private DataSource dataSource;//yml文件中,spring.datasource
    @Autowired
    private UserDetailsService userDetailsService; //实现UserDetailsServiceImpl

    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);//配置数据源
        //在启动的时候会自动创建存放记住我的表(persistent_logins),如果存在会报错(手动创建)
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 图片验证码过滤器
            //创建验证码过滤器,验证器使用自定义错误处理
        ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter(/*myAuthenticationFailureHandler*/);
        //配置验证码过滤url
        //validateCodeFilter.setSecurityProperties(securityProperties);
        validateCodeFilter.afterPropertiesSet();

        //加入过滤器链,在UsernamePasswordAuthenticationFilter之前
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)
        .formLogin()  //表单登陆认证方法,浏览器跳转到specurity默认登陆页面
            //http.httpBasic()//浏览器弹出登陆对话框登陆认证方式
            //.loginPage("/login.html")//自定义登陆页面
            .loginPage("/authentication/require")//自定义登陆url
            .loginProcessingUrl("/authentication/form")//用户登陆提交接口
            .successHandler(myAuthenticationSuccessHandler)
            .failureHandler(myAuthenticationFailureHandler)
            .and()
            .rememberMe()
            .tokenRepository(persistentTokenRepository())//配置remeberMe的token操作
            .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds()) // rememberME 有效期         
            .userDetailsService(userDetailsService) //验证记得我的token
            .and()
        .authorizeRequests() ////设置请求符合访问资源的权限
            .antMatchers(securityProperties.getBrowser().getLoginPage(),"/myLogin.html","/code/*","/authentication/require","/authentication/mobile")//匹配器
            .permitAll()//访问这两个页面不需要认证
            .anyRequest().authenticated() //对任何请求都要登陆认证后才能访问
            .and()
        .csrf().disable()//关闭跨域伪造关闭
                .apply(smsCodeAuthenticationSecurityConfig);
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        //return NoOpPasswordEncoder.getInstance(); //已弃用
        return new BCryptPasswordEncoder();
    }
}
复制代码

数据库表

JdbcTokenRepositoryImpl 类中有一个变量

创建表有两种思路:

  1. 拷贝出sql语句,手动创建

CREATE TABLE persistent_logins (

    username VARCHAR (64) NOT NULL,

    series VARCHAR (64) PRIMARY KEY,

    token VARCHAR (64) NOT NULL,

    last_used datetime NOT NULL

);

  2. jdbcTokenRepository.setCreateTableOnStartup(true);

    在启动的时候会自动创建存放记住我的表(persistent_logins),如果存在会报错(手动创建)

posted @   wangzhilei  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示