Spring boot中使用Spring Security的记住我 remember-me功能

Spring boot中使用Spring Security的记住我 remember-me功能

问题描述:Spring security新手,在登录时加上记住我功能,需要使用框架自带的记住我。

记住的用户数据,在数据库中做了持久化处理

  1. 首先 pom.xml文件中需要引入:
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
            org.springframework.boot
            spring-boot-devtools
            true
        

  1. 定义自己的UserDetailsService 子类
public interface SysUserService extends UserDetailsService {
    /**
     * 根据用户名获取鉴权现象,用于登陆
     *
     * @param username 用户名
     * @return 用户详细信息
     * @throws UsernameNotFoundException
     */
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    
}
public class SysUserServiceImpl implements SysUserService{
   UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
   {
   	//自定义数据库查找用户信息的逻辑
	}
}
  1. 在WebSecurityConfigurerAdapter的子类中,进行如下改动
import com.hanshow.esltemplate.security.*;
import com.hanshow.esltemplate.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.AuthenticationManager;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private SysUserService sysUserService;//自定义的UserDetails子类

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;//配置数据源,这样才能将token信息保存到数据库中

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 身份验证配置,用于注入自定义身份验证Bean和密码校验规则
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(sysUserService);
    }

//注意了 这个是持久化token的bean,和remember-me相关
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        jdbcTokenRepository.setCreateTableOnStartup(false);//启动创建表,自己创建了这里设置false
        return jdbcTokenRepository;
    }

    /**
     * Request层面的配置,对应XML Configuration中的元素
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
	                .and()
                .authorizeRequests().anyRequest().authenticated()
               	 	.and()
                .rememberMe()
	                .userDetailsService(sysUserService)
	                .tokenRepository(persistentTokenRepository()) // 配置 token 持久化仓库
	                .tokenValiditySeconds(3000) // remember 过期时间,单为秒
	                .key("INTERNAL_SECRET_KEY")
	                .and()
                .formLogin()
                    .and()
                .httpBasic();
    }

    /**
     * 返回 RememberMeServices 实例
     *
     * @return the remember me services
     */
    @Bean
    public RememberMeServices rememberMeServices() {
        // 此处的 key 可以为任意非空值(null 或 ""),但必须和前面
        // rememberMeServices(RememberMeServices rememberMeServices).key(key)的值相同
        PersistentTokenBasedRememberMeServices rememberMeServices =
                new PersistentTokenBasedRememberMeServices("INTERNAL_SECRET_KEY", sysUserService, rememberMeTokenRepository);

        // 该参数不是必须的,默认值为 "remember-me", 但如果设置必须和页面复选框的 name 一致
        rememberMeServices.setParameter("remember-me");
        return rememberMeServices;
    }

    /**
     * restful 登陆接口过滤器
     *
     * @return
     */
    @Bean
    public RestAuthenticationProcessingFilter restAuthenticationProcessingFilter() {

        RestAuthenticationProcessingFilter restAuthenticationProcessingFilter = new RestAuthenticationProcessingFilter();
        restAuthenticationProcessingFilter.setAuthenticationManager(authenticationManager);
        
		//rememberMeServices 我的设置在这里了,在上面的configure方法里设置过,但是没生效,还没太搞清楚为什么
        restAuthenticationProcessingFilter.setRememberMeServices(rememberMeServices());
        
        return restAuthenticationProcessingFilter;
    }

}
  1. 在前端,发送数据加上 remember-me=true/on/1,然后使用 Content-Type: application/x-www-form-urlencoded方式往后端传数据,只有这种方式框架才能读取到remember-me的值,之前使用的application/json,debug总是发现进入不了remember-me的逻辑= =,浪费了一些时间。
    测试登录,会发现数据库persistent_logins表多了一条数据:

    至此,记住我功能就完成了

参考:https://www.cnblogs.com/xuwenjin/p/9933218.html 看了对security框架有了更好的理解

你可能感兴趣的:(java,Spring,boot)