一、导言
1、什么是jwt及组成部分
JWT(JSON Web Token)是一种用于在网络应用间安全传递声明(claim)的开放标准。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
头部主要包含了用于描述 JWT 类型以及所使用的签名算法的信息。载荷包含了需要传递的声明(claim),比如用户身份、权限等信息。签名则是对头部、载荷和一个密钥进行的签名,用于验证数据的完整性。
1.1 Header
{"typ":"JWT","alg":"HS256"}
这个json中的typ属性,用来标识整个token字符串是一个JWT字符串;它的alg属性,用来说明这个JWT签发的时候所使用的签名和摘要算法
typ跟alg属性的全称其实是type跟algorithm,分别是类型跟算法的意思。之所以都用三个字母来表示,也是基于JWT最终字串大小的考虑,
同时也是跟JWT这个名称保持一致,这样就都是三个字符了…typ跟alg是JWT中标准中规定的属性名称
1.2 Payload(负荷)
{"sub":"123","name":"Tom","admin":true}
payload用来承载要传递的数据,它的json结构实际上是对JWT要传递的数据的一组声明,这些声明被JWT标准称为claims, 它的一个“属性值对”其实就是一个claim(要求), 每一个claim的都代表特定的含义和作用。
- 英文“claim”就是要求的意思
- 如上面结构中的sub代表这个token的所有人,存储的是所有人的ID;name表示这个所有人的名字;admin表示所有人是否管理员的角色。 当后面对JWT进行验证的时候,这些claim都能发挥特定的作用
- 根据JWT的标准,这些claims可以分为以下三种类型:
A. Reserved claims(保留)
它的含义就像是编程语言的保留字一样,属于JWT标准里面规定的一些claim。JWT标准里面定义好的claim有:
iss(Issuser):代表这个JWT的签发主体;
sub(Subject):代表这个JWT的主体,即它的所有人;
aud(Audience):代表这个JWT的接收对象;
exp(Expiration time):是一个时间戳,代表这个JWT的过期时间;
nbf(Not Before):是一个时间戳,代表这个JWT生效的开始时间,意味着在这个时间之前验证JWT是会失败的;
iat(Issued at):是一个时间戳,代表这个JWT的签发时间;
jti(JWT ID):是JWT的唯一标识。
B. Public claimsC. Private claims(私有)
这个指的就是自定义的claim,比如前面那个示例中的admin和name都属于自定的claim。这些claim跟JWT标准规定的claim区别在于:JWT规定的claim,
JWT的接收方在拿到JWT之后,都知道怎么对这些标准的claim进行验证;而private claims不会验证,除非明确告诉接收方要对这些claim进行验证以及规则才行按照JWT标准的说明:保留的claims都是可选的,在生成payload不强制用上面的那些claim,你可以完全按照自己的想法来定义payload的结构,不过这样搞根本没必要:
第一是,如果把JWT用于认证, 那么JWT标准内规定的几个claim就足够用了,甚至只需要其中一两个就可以了,假如想往JWT里多存一些用户业务信息,
比如角色和用户名等,这倒是用自定义的claim来添加;第二是,JWT标准里面针对它自己规定的claim都提供了有详细的验证规则描述,
每个实现库都会参照这个描述来提供JWT的验证实现,所以如果是自定义的claim名称,那么你用到的实现库就不会主动去验证这些claim
1.3 signature
签名是把header和payload对应的json结构进行base64url编码之后得到的两个串用英文句点号拼接起来,然后根据header里面alg指定的签名算法生成出来的。
算法不同,签名结果不同。以alg: HS256为例来说明前面的签名如何来得到。
按照前面alg可用值的说明,HS256其实包含的是两种算法:HMAC算法和SHA256算法,前者用于生成摘要,后者用于对摘要进行数字签名。这两个算法也可以用HMACSHA256来统称
2、为什么要使用jwt
JWT 的主要优势在于它的无状态性和自包含性。因为 JWT 包含了所有需要的信息,在服务端不需要存储任何状态,只需通过密钥验证 JWT 的有效性即可。这使得 JWT 在分布式系统中非常适用。
JWT的精髓在于:“去中心化”,数据是保存在客户端的。
3、jwt的工作原理
JWT 的工作原理如下:
- 用户使用有效的凭证(如用户名和密码)进行身份认证;
- 服务器验证凭证成功后,生成一个 JWT 并将其发送给客户端;
- 客户端将 JWT 存储起来,通常是在前端的本地存储中(如浏览器的 localStorage 或移动端的 Keychain);
- 客户端在每次与服务器通信时都将 JWT 在请求头或请求参数中携带;
- 服务器对 JWT 进行验证和解码,以获取其中的信息并验证签名的有效性;
- 如果验证成功,服务器可以根据其中的声明来授权用户访问特定资源。
简化工作原理的步骤:
- 是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户
- 之后,当用户与服务器通信时,客户在请求中发回JSON对象
- 为了防止用户篡改数据,服务器将在生成对象时添加签名,并对发回的数据进行验证