SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案

前言

用SpringBoot做一个项目,都要写登录注册之类的方案
使用Cookie或Session的话,它是有状态的,不符合现代的技术
使用Security或者Shiro框架实现起来比较复杂,一般项目无需用那么复杂
使用JWT它虽然是无状态的,也可以载荷用户数据,但还是有很多缺点
  • 缺点1:设置过期时间后,无法强制让它过期,在有效期内它始终可用
  • 缺点2:一次性的,如果用户数据有变,只能重新生成新的JWT
  • 缺点3:安全性,它是base64加密的,如果载荷有重要数据,可以被抓包解析

JWT不适合登录鉴权,适合应⽤场景:⼀次性验证,比如⽤户注册后发⼀封邮件让用户在有效期内激活账户

所以很多项目用的都是Redis+Token方案,简单方便问题少

流程 + lua优化

  1. 设置一个拦截器,不校验登录接口,拦截其他接口

  2. 登录接口接收前端传来的用户名密码,去数据库查询该用户名是否存在,该密码是否正确

  3. 如果正确则表示登录成功,调用生成Token方法,返回Token给前端

  4. Token使用用户id或账号+时间戳+UUID用MD5加密的一串字符串(不建议用其他数据,因为id或账号极少变更的,变更会增加复杂性)

  5. 生成后存储到Redis,把Token当作键,用户数据当作值,并设置过期时间

  6. 生成Token的方法中,还得防止重复调登录接口,不停生成不同的Token,所以先判断数据库中是否存在键,所以保存token键到redis的同时要在redis中再增加一条用户ID为键Token为值的数据,可以验证该用户是否已经生成过token,如下:
    SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案_第1张图片
    SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案_第2张图片

    这个验证token的是已登录后其他请求通过拦截器中验证token的
    SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案_第3张图片
    SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案_第4张图片

  7. 先请求一次reids拿过期时间来判断,再选择生成或者延长

    关于Token续签(延长过期时间)
    假如设置Token五个小时过期需要重新登录,其他的博客可能有刷新token,这些工作需要前端去配合调用,无疑增加了前端和后端的工作量。所以考虑直接用已存在的Token延长时间,因为Token本身是md5加密的,所以安全性还是可以的

  8. 注意到没,判断和生成和续签都需要两次redis请求,一次判断时间,一次读写Token,
    这可能就会导致数据不一致问题,懂了吗?

    所以这部分操作全部交由lua处理
    SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案_第5张图片
    登录方法这个lua脚本中既判断了存在,又判断了是否需要延期,又可以只生成一个token,且只需要请求一次redis。

    接下来是校验其他接口方法,同时也做了验证和续期
    SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案_第6张图片
    这样登录和校验续期都只需要请求一次redis即可,类似分布式锁的实现了,相当于把token当作锁。

    方案只要配置WebMvcConfigurer
    SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案_第7张图片
    自定义一个拦截器,再写一个TokenUtil就好了,是不是很简单
    SpringBoot+Token+Redis+Lua+自动续签极简分布式锁Token登录方案_第8张图片

虽然方案还有一些不完美的,但是不影响性能和使用。有更好的意见大家提出~

原创不易,请勿盲目copy!

你可能感兴趣的:(lua,spring,boot,redis)