JWT介绍
JWT是JSON Web Token的缩写,是为了在网络应用环境间传递生命而执行的一种基于JSON的开放标准。JWT本身没有定义任何技术实现,它只是定义了一种基于token的会话管理的规则,涵盖Token需要包含的标准内容和Token的生成过程,特别使用与分布式站点的单点登录场景
一个JWT Token格式
它有 . 分割成但部分组成,
-
头部
-
负载
-
签名
头部和负载以JSON形式存在,这就是JWT中的JSON,三部分的内容都分别单独经过了 Base64编码,以 . 拼接成一个JWT Token
什么是base64编码?
Base64编码是一种用64个字符来表示任意数据二进制的编码方法。它使用了AZ、az、0-9这62个字符,再加上两个额外的字符(通常是+和/),来Base64编码通常用于在URL、XML、JSON等文本传输过程中输入二进制数据,因为它能够将二进制数据转换成文本格式,方便在文本协议中传输,并且因为不会因为特殊字符而导致解析问题。
Base64编码的特点包括:
-
可打印字符:Base64编码使用了可打印字符集,编码后面的数据可以在文本中显示,不会出现乱码。
-
大小增加:由于Base64编码将二进制数据转换成文本格式,因此编码后的数据大小会比原始数据增加约1/3。
-
不可逆:Base64编码是一种不可逆的编码方法,无法通过编码后的文本恢复出原始的二进制数据。
-
补充填充:如果编码后的数据长度不是4的倍数,会使用=字符进行填充。
比如说,一个16字节的二进制数据经过Base64编码后通常会变成22个字符。Base64编码的实现很简单,就是将3个字节的二进制数据转换成4个字符的文本格式。
Header
JWT 的Header中存储了所使用的加密算法和Token类型。
{ "alg": "HS256", "typ": "JWT" }
PayLoad
Payload 表示负载,也是一个JSON对象,JWT规定7个官方字段供使用
-
除了官方字段,开发者也可以自己指定字段例如下面内容
注意:JWT默认是不加密的,任何人都可以读到,所以不要把秘密信息放到这个部分。这个JSON对象也要使用Base64URL算法转成字符串。
Signature
signature部分是对前两部分的签名,防止数据篡改
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知到,不能泄露给用户。然后使用Header指定的签名算法(默认是HMAL SHA256),按照下面的公式产生签名。
即:
将base64加密后的header和base64加密后的payload 用 . 连接组成字符串 然后使用header中声明的加密方式(HS256)加密 + 加盐 (关于加盐不理解的同学可以单独了解,这里不做展开介绍) 对HS256加密后的密文再做base64加密得到第三段字符串
JWT验证
校验方式(和加密方式正好反过来)
-
获取
token
-
对
token
进行切割 -
对第二段进行
base64
解密并获取payload
信息,检测token
是否已经超时? -
把第一段和第二段进行拼接再次执行
SH256
加密,再与base64
解密后的第三段密文进行比较,如果经比较得出密文是相等则认证通过
JWT的优缺点
JWT拥有基于Token的会话管理方式所拥有的一切优势,不依赖于cookie,使得其可以防止CSRF攻击,也能在禁用Cookie的浏览器环境中使用。
JWT最大的优势是服务端不需要存储Session,使得服务端认证鉴权业务可以更方便的扩展,避免存储Session所需要引入的redis等组件,降低了系统架构复杂度。但这也是JWT最大的劣势,由于有效期存储在token中,JWT Token一旦签发,就会在有效期内一直可用,无法在服务器废止,当用户进行登录操作时,只能依赖客户端删除本地存储的JWTtoken,如果需要禁用用户,单纯使用JWT无法做到
token验证原理
以下是 Token 验证的基本工作原理:
-
用户登录: 用户提供用户名和密码进行登录。服务端验证用户身份后,生成一个包含用户信息的 Token。
-
Token颁发: 服务端将生成的 Token 返回给客户端。通常,Token 包含用户的标识信息、过期时间、权限等相关信息,并使用加密算法进行签名。
-
客户端存储: 客户端将 Token 存储在安全的地方,通常是在内存中或浏览器的本地存储(如 localStorage 或 sessionStorage)中。
-
请求携带 Token: 在每次需要身份验证的请求中,客户端都会将 Token 添加到请求头、请求体或请求参数中,并发送给服务端。
-
服务端验证: 服务端在收到请求后,通过解析 Token 来获取用户信息,并验证 Token 的有效性。验证包括检查签名、过期时间等。
-
授权检查: 服务端根据 Token 中包含的权限信息来检查用户是否有执行该请求所需的权限。
-
响应处理: 如果 Token 有效且权限满足,服务端处理请求并返回相应的数据;如果 Token 无效或权限不足,服务端返回相应的错误信息。
-
Token 刷新: 在一些情况下,Token 可能会过期。客户端可以使用 refresh token 或重新提供用户名密码等方式获取新的 Token。
基于JWT实现认证实践
前面讲的Token,都是Access Token,也就是访问资源接口时所需要的Token,还有另外一种Token,Refresh Token,通常情况下,Refresh Token 的有效期会比较长,而Access Token的有效期比较短,当Access Token 由于过期失效时,使用Refresh Token就可以获取到新的Access Token,如果Refresh Token 也失效了,用户只能重新登陆了。