用户登录功能

用户登录成功要返回登录凭证给用户

Cookie和Session

session id

每个用户都有自己的session, 不同用户之间session是隔离的,这个由所有的session插件或者tomcat服务器自己维护。

使用服务器自身的session注意问题

手机验证码的登录方式,一定要保证在当前用户去session中拿自己数据(也就是验证码)的时候一定是他获取验证码的那个手机号,也就是手机号和验证码一定要对应上。否则可能注册别人的手机号

【看如下操作】:
用户输入 手机号:131xxx,获取到验证码:9721
而在登录的时候修改了手机号 也就是 用户输入了新手机号:188xxx,验证码:9721
这样会登录/注册成功。显然是个BUG!

【解决办法】
修改session中保存的key value
由原来{"code", 9721}
修改为{"{用户获取验证码的手机号}", 9721}

ThreadLocal取代每次都从session中获取登录用户?

  1. 可以在同一线程中很方便的获取用户信息,不需要频繁的传递session对象。

问题: 使用tomcat服务器么? 如果tomcat 使用的线程池,那么线程复用的问题就可能存在,同一个ThreadLocal(final的),会不会产生数据的错乱呢?

肯定会错乱的,所以要在这次请求结束时 调用remove方法清除。

Reids + Token 实现登录

分布式环境下用户信息保存到服务器的Session下就不靠谱了,不同节点的服务器sessioin数据并不会主动同步。
用户的请求可能会被分发到没有保存这个用户的Session服务器下,拿不到用户登录的数据。
这个时候就可以考虑使用 Redis + Token 的机制来实现

用户登录(输入用户名和密码) ---> 服务器与数据库保存的用户名和密码对比,对比成功为用户创建Token, 保存到redis中,并返回给用户
---> 前端保存这个Token到Header中,一般key为authorization, value为Token

以后每次请求都带上这个Token, 服务从Request Header中获取Token字段,去redis中获取key为Token的Value值
这里的value值一般就是未加密的用户信息了{"userId":"10001", name:"zhansan", age:"18"}

后面就可以根据用户id,去查询其他这个用户的数据,返回给这个用户就好了。

JWT

但是Redis作为一种中心化的存储服务,容易给分布式系统造成性能瓶颈,如果中心化服务器出现故障就会造成所有服务器出现故障。
所以我们还是希望会话数据又客户端(web页面,移动端、小程序等)保存,接口尽可能是无状态的。

服务端返回一个JWT Token给客户端, JWT Token由三部分组成 header + payload + 签名算法

**数据签名**: 

JWT的问题:如何token设置有效期很长,那么即使退出登录,这个token还是有效的
解决办法:服务端维护一个token黑名单,客户端要删除token信息

JWT如何续签?

OAuth2.0

https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

posted @ 2024-04-14 16:02  bestwell  阅读(18)  评论(0编辑  收藏  举报