Springboot 整合 Spring Security 配合thymeleaf,mysql实现记住登录

原理: 用户首次登录发送请求成功通过过滤器后会被生成一个token,这个token和用户名一一对应,且会被放入Cookie与数据库中,用户在之后的登陆请求中携带的Cookiee的token会与数据库中的比对,成功的话会调用UserDetailsService获得用户的信息并返回,至此结束。

​ 仔细想想会发现,这种比对方法在Spring security中十分常见,不去解密而是利用hash的一致性,单向加密对比,防止了由于秘钥泄露造成的安全问题。(个人理解)

​ 使用mysql 所以不讲解内存方法

具体实现:

  1. 数据库中建表

    CREATE TABLE persistent_logins (
    	username  VARCHAR(64) NOT NULL,
    	series    VARCHAR(64) NOT NULL PRIMARY KEY,
    	token     VARCHAR(64) NOT NULL,
    	last_used TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    );
    
  2. 注入数据源

    @Autowired
        DataSource dataSource;
    
  3. 实现UserDetailsService

    @Service
    public class UserSecurityImpl implements UserDetailsService {
        @Autowired
        UserService userService;
        @Autowired
        PasswordEncoder passwordEncoder;
    
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            com.salty.pojo.User user = userService.findByUsername(username);
            if(user == null) {
                throw  new UsernameNotFoundException("用户不存在");
            }
            //以后和数据库对接
            userService.updateLastLogin(user.getId(), 		TimeUtil.getFormatTimeForSix());
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("normal"));
            User ret = new User(user.getUsername(),user.getPassword(),authorities);
            return ret;
        }
    }
    
  4. 注入Bean:

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

    rememberMe()//记住我功能开启
    .tokenRepository(persistentTokenRepository())//这就是之前的Bean
    .tokenValiditySeconds(60*60)//过期时间 单位看前面是秒
    .userDetailsService(userDetailsService)//通过用户名获取登录用户信息
    .and()//继续链式调用
    

最后还有前端的

<input name="remember-me" type="checkbox" value="true"/> 记住我

具体登录form你们自己写写 我就不贴了(国际化写的太乱了),别忘了form登录要在configure中配置

到此可以说已经完成了,登录后应该能在数据库中看到有对应的token进入了。

不用thymeleaf的可以右上角了,下面是我thymeleaf踩的坑

事情经过: 我大部分数据是在登录后的controller跳转中注入到session里面的,之后传给前端的thymeleaf使用,一开始开发的时候使用的非常方便,但是到了这里就会有一个巨大的问题,如果用户收藏了需要登录才能进入的网页,之后直接访问了该url,那么在记住我实现后的情况下不会经过loginController,也就是说前端的thymeleaf没有值注入,导致一大片error null。

解决方法:

​ 通过别的方式注入值,或者干脆放弃thymeleaf,直接用ajax,以后还方便前后端分离

​ 实在不死心就用SecurityContextHolder.getContext().getAuthentication().getName();去获得用户名之后去调信息吧,可以尝试使用before切片注入,也可以写在方法里,随你自己发挥

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值