Redis学习记录----登录功能

112 阅读3分钟

登录功能

基于Session实现短信登录

image.png

发送验证码

校验验证码、注册

创建线程池

public class UserHolder {

    private static ThreadLocal<User> tl =new ThreadLocal<User>();

    // 存数据
    public static void saveUser(User user){
        tl.set(user);
    }

    //取数据
    public static User getUser(){
        return tl.get();
    }

    //删除数据
    public static void removeUser(){
        tl.remove();
    }

}

image.png

image.png

image.png

登录校验拦截器

由于有些方法需要在发送请求时校验登录状态(即登录后才能发送请求),而不同的业务接口如果各自写登录校验会冗余,所以使用一个全局的登录拦截器进行拦截,同时记录下登录的状态信息,以便后续使用

image.png

定义登录拦截器

image.png

配置拦截器生效

选择放行哪些方法(不需要拦截校验)

登录校验调用

image.png

基于Redis实现共享session登录

在多机部署下,请求是随机地向某个服务器发送的,所以当进行一次登录时,session是存在对应的服务器上,登陆成功后执行其他请求方法,又是随机地向某个服务器发送请求,如果恰好该服务器上没有session,则发送请求失败

验证码由存入session改为存入redis,同时为了区分,采用phone作为key,
登录成功后手动生成一个token作为用户凭证(key)将登录用户存入redis中
则校验登录状态只需要根据token去redis获取用户即可,获取到且非空则放行,同时将用户存入ThreadLocal,使得后续可以随时获取用户信息(属性/字段)

image.png

发送验证码

验证码存入redis

image.png

校验验证码、注册

image.png

image.png

TODO:StringRedisTemplate只允许存入String类型的key、value,而userDTO中存在非String类型

image.png

最好把字符串login:token封装成枚举类常量LOGIN_USER_KEY

image.png

可以自己指定规则,将非String类型的转为String类型

image.png

修改登录校验拦截器

原先在MvcConfig配置类中配置拦截器时采用的new一个登录拦截器,而登录拦截器并没有使用@Component注解将登录拦截器交给SpringMVC,因此不能被SpringMVC注入想要的功能,即无法注入SpringRedisTemplate,所以只能使用构造方法

image.png

原先是从session中获取用户,现在使用token获取redis中的用户

image.png

修改拦截器配置

image.png

拦截器优化

存在的问题:假设我们现在做了一个token有效期的刷新,用户如果未操作,登录态最多保持30min,如果操作了(发送了某些请求),就需要刷新登录态,即刷新token的有效期,对于需要用户登录校验的方法,可以在校验成功后刷新token有效期,但对于不需要用户登录校验的方法(即被放行的方法),拦截器对它不生效,所以也就不进行登录校验并刷新token,导致对于这些方法,最多只能保持30min可操作时长

这个问题本质上是因为token有效期刷新和登录校验放在了同一个拦截器,而token有效期刷新是针对所有方法,登录校验只针对部分方法,那么我们只需要把token有效期刷新和登录校验分离开即可,因此可以设置两个拦截器

image.png

具体实现

刷新有效期就是再次设置过期时间

image.png

将用户信息存入线程池的操作在上面那个拦截器做了,所以这个拦截器不需要用到stringRedisTemplate操作redis去存用户信息到线程池

image.png

配置两个拦截器的优先顺序:order值越小的拦截器越优先

image.png