SpringSecurity之RememberMe实现

RememberMe的实现一定离不开Token的持久化存储。来看看使用Security应该怎么用RememberMe功能

RememberMe实现的两个模式

Security中有着两个实现RememberMe功能的实现类,但是都离不开持久化Token。

  • AbstractRememberMeServices的实现类
    • PersistentTokenBasedRememberMeServices服务端或数据库保存Cookie
      • 其中tokenRepository属性时存储的方案:
        • InMemoryTokenRepositoryImpl 存储到内存中(Map)
        • JdbcTokenRepositoryImpl 存储到数据库中
    • TokenBasedRememberMeServices客户端保存Cookie
      • 通过对Token串的加密和解密进行认证

Token持久化到数据库

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    public UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder () {
        return new BCryptPasswordEncoder();
    }



    /**
     * PersistentTokenRepository持久化Token实现类:
     *  1. JdbcTokenRepository
     *  2. InMemoryTokenRepository
     * @return Remember-Me的TokenRepository
     */

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        // 设置JdbcDaoSupport对象中的JdbcTemplate所需要的DataSource对象。
        jdbcTokenRepository.setDataSource(dataSource);
        // 自动创建表结构,在没有表的情况下,会自动生成persistent_tokens表
        // jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

	// 无需自己创建。
    // security自动根据是否存在tokenRepository来创建PersistentTokenBasedRememberMeServices或者TokenBasedRememberMeServices
    //
    // @Bean
    // public RememberMeServices rememberMeServices() {
    //     PersistentTokenBasedRememberMeServices persistentTokenBasedRememberMeServices = new PersistentTokenBasedRememberMeServices("yyl", userDetailsService, persistentTokenRepository());
    //     // 持久化token有效期时长
    //     persistentTokenBasedRememberMeServices.setTokenValiditySeconds(AbstractRememberMeServices.TWO_WEEKS_S);
    //     return persistentTokenBasedRememberMeServices;
    // }



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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling().accessDeniedPage("/test/unAuthority");
        http.formLogin() // 自定义登录配置
                .loginPage("/login.html") // 登录页url
                .loginProcessingUrl("/user/login") // 验证登录的url
                .defaultSuccessUrl("/test/index.html") // 默认登录成功,将重定向到的url
                // .failureUrl("/test/loginFailed.html").permitAll() // 默认登录失败,将重定向到的url
                .permitAll()
            .and().authorizeRequests()
                .antMatchers("/", "/test/hello", "/user/login", "/test/current", "/test/sessionInvalidate").permitAll() // 设置哪些路径可以直接访问,不需要认证
                .antMatchers("/test/managepage.html").hasAuthority("admin,manage")
                .antMatchers("/test/anyRole").hasAnyRole("zs", "ls")
                .anyRequest().authenticated()
            .and().csrf()
                .disable();
        // 退出之后,跳转到LogoutSuccess需要权限才能进去。 permitAll将前面的地址设置为不需要权限就可以进去。  与permitAll相对应的是authenticated
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/logoutSuccess").permitAll();
		// 无需自己创建。
        // security自动根据是否存在tokenRepository来创建PersistentTokenBasedRememberMeServices或者TokenBasedRememberMeServices
        // http.rememberMe().rememberMeServices(rememberMeServices());
        http.rememberMe().tokenRepository(persistentTokenRepository()).userDetailsService(userDetailsService)
                // .tokenValiditySeconds(AbstractRememberMeServices.TWO_WEEKS_S);
                .tokenValiditySeconds(30);
    }
上一篇:【智能合约】Go语言调用以太坊 | geth


下一篇:SpringSecurity权限认证(三)