第4阶段-登录模块.md 5.2 KB

登录模块

相关技术:微信登录、短信、自定义注解、aop、策略模式、分布式事务

我们的单点登录是有状态登录,并且有多种登录方式,所以结合了策略模式,定义了抽象策略类,并提供了具体策略实现包括:

  1. 账户登录:用户名和密码
  2. 微信登录:openId
  3. 手机验证码:短信

我们还使用了分布式事务:例如微信登录时,如果用户已存在则直接登录,否则还要隐式去注册用户并初始化账户信息,由于用户和账户是两个服务。

分布式事务理论、分布式事务解决方案、seata相关理论

登录方式

手机验证码

前端就会验证手机号是否合法,如果合法,点击发送验证码,后台获取手机号:

  • 验证手机号是否合法
  • 查询redis中是否已发送过,如果已发送过则抛出异常,提示已发送
  • 查询发送频率,如果发送频率超过xxx值,则抛出异常,提示发送太频繁
  • 生成短信验证码,以手机号作为key,以code作为value,缓存到redis同时设置过期时间
  • 调用阿里的短信接口,发送短信给用户

用户获取手机验证码之后,可以输入验证码,点击登录按钮,后台可以获取手机号及验证码:

  • 验证手机号的合法性
  • 根据手机号作为key到redis中查询验证码,和用户输入的验证码进行比较,如果不一致则抛出异常,提示验证码错误
  • 根据手机号到mysql中进行用户查询,如果为空,则说明用户第一次用手机号登录,则隐式注册用户
    • 新增用户信息
    • 初始化账户信息
  • 通过uuid生成token,以token作为key,以用户作为value缓存到redis中
  • 响应token给前端,保存到localStorage中

微信登录

前端会生成code,并把code提交到后台:

  • 调用微信的远程接口:需要传递code、appid、secretkey给微信服务器
  • 微信服务响应openId和sessionKey,咱们使用openId作为用户的唯一标识
  • 根据这个唯一标识查询mysql的用户表,判断该用户是否已注册过,如果未注册则隐式注册用户
    • 新增用户信息
    • 并且初始化账户信息
  • 如果已注册,或者隐式注册成功,则通过uuid生成token
  • 以token作为key 以用户信息作为value缓存到redis中
  • 响应token给前端,保存到localStorage中

账号密码

账户登录:用户名和密码

前端用户输入用户名和密码之后,我们可以获取这些参数,在后台:

  • 根据用户名查询用户
  • 判断用户是否为空,如果为空则抛出异常,提示用户名或者密码错误
  • 如果不为空,则对用户输入的密码进行加盐加密,然后和数据库查询的用户密码进行比较
    • 如果不一致则说明密码错误,抛出异常提示用户名或者密码错误
    • 如果一致则说明用户名和密码都正确了
  • 通过uuid生成token信息,并把token和用户作为k和v缓存到redis中
  • 把token返回给前端,保存在localStorage中

身份认证的流程

自定义注解@GuiguLogin

@GuiguLogin注解的作用

1.验证用户是否登录
2.获取用户信息

其他的实现方式

Gateway网关实现全局过滤器

项目采用自定义注解、AOP方式实现登录控制,我们只需要在需要登录的接口添加此注解即可。

具体开发步骤

有些接口需要登录才能使用,需要通过token获取登录信息并验证是否登录,为了通用我们使用了自定义注解 +

AOP封装了登录注解。

  1. 自定义了登录注解@Login
  2. 通过环绕通知针对注解进行了赋能
    1. 在环绕通知中获取请求对象的token:controller很好获取,通过RequestContextHolder对象在通知方法中获取request对象
    2. 通过token获取redis中的登录信息
    3. 如果登录信息为空则抛出异常
    4. 如果登录信息不为空则把登录信息(userId和userName)放入threadLocal 传递给后续Service
    5. 业务处理完成之后要释放ThreadLocal防止内存泄漏

image-20231010152130137

介绍ThreadLocal对象

https://blog.csdn.net/u010445301/article/details/111322569

修改用户信息

具体流程

  • 前端点击修改进行数据回显
  • 前端将修改的数据提交
  • 后台接收到数据进行更新操作

其他问题

小程序上登录了,在app上也登陆了,并且添加了收藏,小程序能不能看到

​ 能看到。不管任何平台(小程序、ios、andriod、web),最终token对应的用户是同一个所以一端添加收藏另 一端是可以看到了

能不能多端同时登录?如何做到多端不能同时登录?怎么踢掉其他端登录状态

可以多端同时登录:一个用户在多端可能同时存在多个token。

image-20240320142049445

token被盗了怎么办?

在登录信息中添加登录用户的ip。将来每次身份认证时获取请求用户id,两个ip进行比较,如果不一致说明是盗用的,则抛出异常跳转到登录页面。

生成一个随机盐。jwt(有效载荷 userId IP)

所有方案都无法防止100%盗用,只能尽量解决。