您现在的位置是:首页 >学无止境 >项目技术分析-用户登陆验证(JWT&token&Session对比)网站首页学无止境

项目技术分析-用户登陆验证(JWT&token&Session对比)

Harry恒 2023-07-16 12:00:02
简介项目技术分析-用户登陆验证(JWT&token&Session对比)

登录技术选型

在复盘项目登陆验证方法时,发现之前选用的方法其实并不合理,遂产生学习整理登陆方式的想法,于是有了这篇文章,主要是讨论理论,实际代码可以参考网上已有文章
1、JWT+redis(一开始项目使用的是这种方式、但后面发现这种方法并不合理)
2、token+redis
3、JWT
4、session

JWT

定义与结构

JWT——Json web token
就是令牌token,是一个String字符串,由3部分组成,中间用点隔开
JWT结构:
header 头:
包含令牌的类型和使用的签名算法
Payload荷载
就是装载数据的地方,包含声明(有关用户信息(用户名、密码)和其他数据的声明)
signature 签名
将header和payload经过
base64加密后的数据经
过加盐后进行二次加密。

JWT登录验证流程

1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码
2、后端收到请求,验证用户名和密码,验证成功,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串
3、前端拿到token,并跳转路由页面
4、前端每次调后端接口,都要在请求头中加token
5、后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401

JWT优点缺点:

1、JWT无状态,服务器不用存储登陆状态信息,减轻服务器压力
2、不需要依赖 Cookie ,因此可以避免 CSRF 攻击

1、注销登录等场景下 JWT 还有效,服务端不能主动让token失效
2、续签 问题

基于上述场景:JWT适合作用场合:

  • 有效期短
  • 只希望被使用一次
  • 跨域登录(协议、域名、端口号不一致)(这里也是我们项目采用JWT的一个原因,又Springboot和Flask两个后端)

比如,用户注册后发一封邮件让其激活账户,通常邮件中需要有一个链接,这个链接需要具备以下的特性:能够标识用户,该链接具有时效性(通常只允许几小时之内激活),不能被篡改以激活其他可能的账户,一次性的。这种场景就适合使用jwt。

针对JWT的缺点,有没有解决方法呢

1、注销之后token还有效的问题
** 将 token 存入redis 或者建立黑名单机制**

redis 内存数据库在这里是是不错的选择。如果需要让某个 token 失效就直接从 redis 中删除这个 token 即可。但是,这样会导致每次使用 token 发送请求都要先从 DB 中查询 token 是否存在的步骤,而且违背了 JWT 的无状态原则。

2、续签问题
我们在 redis 中单独会每个 jwt 设置了过期时间,每次访问时刷新 jwt 的过期时间,若 jwt 不存在与 redis 中则认为过期。但这也违背了 JWT 的无状态原则。
综上所述,JWT只适合一些小型且安全性要求不高的项目,如果使用JWT+redis其实是有违JWT设计初衷;

Redis+token

1 以用户id为key,生成的token为value,缓存到redis中并设置过期时间
2 以生成的token为key,用户信息为value,缓存到redis中并设置过期时间
最后将token及用户信息返回给前端,前端将token放在header中,调用其他接口时都携带着。
如果退出登录,则将上面的两条信息从redis中删除即可

Session + Cookie

参考文章1
参考文章2

为什么要使用session?

HTTP协议的无状态性,指的是客户端的每次HTTP请求都是独立的,连续多个请求之间没有直接关系,服务器不会主动保留每次HTTP请求的状态

Session登陆验证工作流程


很多时候我们都是通过 SessionID 来实现特定的用户,SessionID 一般会选择存放在 Redis 中。举个例子:

  1. 用户成功登陆系统,然后返回给客户端具有 SessionID 的 Cookie 。
  2. 当用户向后端发起请求的时候会把 SessionID 带上,这样后端就知道你的身份状态了。

多服务节点下Session-Cookie

1、每个服务器保存的用户session一致
2、单独使用一个数据节点进行保存

如果没有 Cookie 的话 Session 还能用吗?

1、将SessionID 保存到cookie当中是常规做法,也可以放在请求的 url 里面https://harry.com/?Session_id=xx

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。