一、为什么使用JWT
HTTP是无状态的,开发人员需要基于HTTP来模拟实现状态的保存。经典的实现用户登录的做法是用Session,用户登录验证成功后,服务端生成SessionId。服务端会将SessionId与登录的用户信息的对应关系保存在服务器内存中,同时将SessionId返回给浏览器端,sessionId一般存储在浏览器Cokiee中,浏览器端的每次请求都携带SessionId,服务端可以通过SessionId从服务器的内存中取到用户信息,这就实现了用户登录功能。对于分布式集群环境,Session数据一般保存到所有集群实例都能访问的状态服务器上,如Redis、Memcached、关系数据库等。
但是,在分布式环境下,特别是在“前后端分离、多客户端”时代,Session暴露出很多问题。
1. 如果session数据存储到内存中,当登录用户量很大的时候,Session数据就会占用非常多的内存,且无法支持分布式集群环境。
2. 如果Session数据保存到Redis等状态服务器中,它可以支持分布式集群环境,但是没遇到一次客户端请求都要向状态服务器获取一次sessions数据,会导致请求的响应速度变慢。
二、JWT是什么
JWT全称是JSON Web Token,JWT是使用json格式来保存令牌信息的。JWT是将登录信息保存到客户端(解决了以上session暴露出的问题),为防止数据造假,保存在客户端的令牌经过了签名处理,签名的密钥只有服务端知道。每次服务端接收到客户端提交的令牌的时候都会检查一下签名,检查签名通过,对令牌进行解码,服务端从而知道当前登录信息,若发现数据被篡改,则拒绝接受客户端提交的令牌。
JWT分为头部header、负载payload、签名sinature三部分。header保存加密算法的说明,payload保存的是用户基本信息,signature是根据header和payload一起算出来的值。
三、JWT缺点及处理方案
缺点:JWT在有效期内一直有效,无法被提前撤回。如用户被删除、用户已经注销登录等jwt令牌需要被提前撤回。
方案:
1、使用Redis保存令牌,每次登录更新用户JWT,上一次登录的JWT令牌与在Redis中存储的令牌不一致或Redis中没有对应的令牌,就拒绝请求。
2、refresh_token+access_token 用户登录生成一个jwt令牌作为access_token,同时生成一份refresh_token,将refresh_token存储到redis中,用户注销时删除在redis中存储的refresh_token。客户端每次请求携带refresh_token和access_token,服务端先判断是否存在携带的refresh_token,如果不存在,拒绝请求。
3、在用户表中增加一个整数类型的列JWTVersion,代表最后一次发放出去令牌的版本号。每次发放时,JwtVersion的值自增,同时将其放到JWT的负载中。当需要撤回用户令牌时,也把JWTVersion的值自增,每次请求时,先将JWT令牌中的JWTVersion与数据库表中的JWTVersion作比较,如果数据库中的值更大,则拒绝请求。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下