02. Spring Security rememberMe

02. Spring Security rememberMe

参考:

https://blog.csdn.net/yuanlaijike/article/details/80249869

接着上一讲

修改login.html

使用简单的记住我, 但是不安全

#login.html

    <div class="form">
        <h3>账户登录</h3>
        <input type="text" placeholder="用户名" name="username" required="required"/>
        <input type="password" placeholder="密码" name="password" required="required"/>
        <!--        自动登入设置的name必须是remember-me-->
        <label><input type="checkbox" name="remember-me"/>自动登录</label>
        <button type="submit">登录</button>
    </div>

添加rememberMe()

#配置类

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/").permitAll()
                .and()
                .logout()
                .and()
                .rememberMe();
    }

默认cookie存储2周

Spring security 还提供了另一种相对更安全的实现机制

在客户端的 Cookie 中,仅保存一个无意义的加密串(与用户名、密码等敏感数据无关),然后在数据库中保存该加密串-用户信息的对应关系,自动登录时,用 Cookie 中的加密串,到数据库中验证,如果通过,自动登录才算通过。

#基本原理

当浏览器发起表单登录请求时,当通过 UsernamePasswordAuthenticationFilter 认证成功后,会经过 RememberMeService,在其中有个 TokenRepository,它会生成一个 token,首先将token 写入到浏览器的 Cookie 中,然后将 token、认证成功的用户名写入到数据库中。

当浏览器下次请求时,会经过 RememberMeAuthenticationFilter,它会读取 Cookie 中的 token,交给 RememberMeService 从数据库中查询记录。如果存在记录,会读取用户名并去调用 UserDetailsService,获取用户信息,并将用户信息放入Spring Security 中,实现自动登陆。

RememberMeAuthenticationFilter 在整个过滤器链中是比较靠后的位置,也就是说在传统登录方式都无法登录的情况下才会使用自动登陆。

#代码实现

首先需要创建一张表来存储 token 信息:

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;

在 WebSecurityConfig 中注入 dataSource ,创建一个 PersistentTokenRepository 的Bean:

@Autowired
private DataSource dataSource;

 @Bean
 public PersistentTokenRepository persistentTokenRepository(){
     JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
     tokenRepository.setDataSource(dataSource);
     // 如果token表不存在,使用下面语句可以初始化该表;若存在,请注释掉这条语句,否则会报错。
//        tokenRepository.setCreateTableOnStartup(true);
     return tokenRepository;
 }

如果使用setCreateTableOnStartup(true)则会再当前库中生成一个表名为persistent_logins的表

修改配置中的登入设置

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/").permitAll()
                .and()
                .logout().permitAll()
                .and()
                //记住我默认2周
                .rememberMe()
                //设置token有效时间
                .tokenValiditySeconds(60)
                .tokenRepository(persistentTokenRepository());
                .userDetailsService(userDetailsService);
posted @ 2020-05-15 01:06  CyberPelican  阅读(149)  评论(0编辑  收藏  举报