天天看點

Spring Security(四)自動登入-持久化令牌方案

一.简介

    持久化令牌方案在交互上与散列加密方案一致,都是在用户勾选Remember-me之后,将生成的令牌发送到用户浏览器上,并在用户下次访问系统时读取该令牌进行认证。不同的是,它采用了更加严谨的安全设计。

    在持久化令牌方案中,最核心的是series和token两个值,它们都是用MD5散列过的随机字符串。不同的是series仅在用户使用密码重新登录时更新,而token会在每一个session中都重新生成。

    这样设计的好处?

    首先解决了散列加密方案中一个令牌可以同时在多端登录的问题。每个会话都会引发token更新,即每个token仅支持单实例登录。

    其次,自动登录不会导致series变更,而每次自动登录都需要同时验证series和token两个值,当该令牌还未使用过自动登录就被盗取时,系统会在非法用户验证通过后刷新token值,此时在合法用户的浏览器中,该token值已经失效。当合法用户使用自动登录时,由于该series对应的token不同,系统可以推断该令牌可能被盗用,从而做一些处理。例如清理该用户自动登录令牌,并通知该用户可能已被盗号等。

二.实战

1.创建一张persistent_logins表

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for persistent_logins
-- ----------------------------
DROP TABLE IF EXISTS `persistent_logins`;
CREATE TABLE `persistent_logins` (
  `username` varchar(64) COLLATE utf8mb4_bin NOT NULL,
  `series` varchar(64) COLLATE utf8mb4_bin NOT NULL,
  `token` varchar(64) COLLATE utf8mb4_bin NOT NULL,
  `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
           

2.WebSecurityConfig配置

package com.zit.springsecurity.configuration;

import com.zit.springsecurity.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;

import javax.sql.DataSource;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Autowired
    @Qualifier("myDataSource")
    private DataSource dataSource;


    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(myUserDetailsService).passwordEncoder(new MyPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);

        http.authorizeRequests()
                .antMatchers("/admin/api/**").hasRole("ADMIN")
                .antMatchers("/user/api/**").hasRole("USER")
                .antMatchers("/app/api/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
                .formLogin()
                .and()
                // 添加自动登录功能,默认为简单散列加密
                .rememberMe().userDetailsService(myUserDetailsService)
                .tokenRepository(jdbcTokenRepository);
    }
}
           

3.效果

Spring Security(四)自動登入-持久化令牌方案
Spring Security(四)自動登入-持久化令牌方案

繼續閱讀