jwt json web token的原理
JWT(JSON Web Token)是一种用于在网络应用环境间安全地传递信息的标准格式。它基于 JSON 格式,可以在各个系统之间交换信息,并且能够验证信息的真实性。JWT 的原理基于签名技术来确保数据的完整性和身份验证。
JWT 的组成
一个标准的 JWT 通常由三个部分组成,分别是:Header(头部)
Payload(载荷)
Signature(签名)
这三个部分通过点(.)连接起来,形成一个字符串:Header.Payload.Signature。1. Header(头部)
头部通常由两部分信息组成:类型(typ):通常为 "JWT"。
签名算法(alg):例如 HS256(HMAC SHA-256)或 RS256(RSA SHA-256)。
示例:json
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload(载荷)
载荷部分包含了要传递的声明(claims)。声明是关于实体(通常是用户)和其他数据的声明。JWT 有三种类型的声明:注册声明(Registered Claims):如 iss(签发者)、exp(过期时间)、sub(主题)、aud(受众)等。这些是 JWT 的标准字段,但并不是强制要求。
公共声明(Public Claims):这些是可以自由使用的声明,但为了避免冲突,应该在 IANA JSON Web Token Claims 中注册。
私有声明(Private Claims):这类声明是自定义的,通常用于两个系统之间共享的非公开信息。
示例:json
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
3. Signature(签名)
为了防止 JWT 被篡改,需要用到签名部分。签名是通过以下方式生成的:将编码后的 Header 和 Payload 连接起来(Base64UrlEncode(Header) + "." + Base64UrlEncode(Payload))。
使用指定的算法和密钥对这个字符串进行签名。
例如:如果使用 HS256(HMAC SHA-256),签名是通过以下步骤生成的:
plaintext
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
这样,签名部分就保证了 JWT 的完整性,防止了数据被篡改。JWT 工作流程
客户端登录: 用户使用用户名和密码等凭证登录后,服务器验证其身份。
生成 JWT: 登录成功后,服务器根据用户信息生成 JWT。这个 JWT 将包含用户的身份信息和一些附加的声明(如过期时间、签发者等)。
将 JWT 发送给客户端: 服务器把 JWT 发送到客户端,通常会将其保存在浏览器的 localStorage 或 sessionStorage 中。
客户端使用 JWT 进行身份验证: 客户端在发送每个请求时将 JWT 放入 HTTP 请求的 Authorization 头中,通常是 Authorization: Bearer <JWT>。
服务器验证 JWT: 服务器接收到请求后,会验证 JWT 的合法性。验证步骤包括:
解码 JWT,检查 Header 和 Payload 是否被篡改。
检查 JWT 的签名是否有效。
检查 JWT 的有效期(如 exp)。
处理请求: 如果 JWT 验证通过,服务器就会处理该请求。如果验证失败,服务器通常会返回 401 未授权的错误。
JWT 的优势
无状态(Stateless): JWT 是自包含的,所有信息都包含在 Token 内,服务器不需要存储会话信息。这意味着它可以扩展到分布式系统中。
易于扩展: JWT 的 Payload 可以包含自定义数据,允许你在 Token 中存储任意信息。
跨平台: JWT 是基于 JSON 的,可以轻松地与不同平台(如前端应用、后端服务等)进行通信。
JWT 的缺点
过期后无法撤销: 如果 JWT 的过期时间很长(例如几个小时或几天),即使用户退出或改变密码,JWT 仍然有效,直到过期。
Token 体积较大: 因为 JWT 包含用户信息和签名数据,它的体积比传统的 Session ID 要大,可能影响性能。
JWT 示例
假设我们有一个 JWT,它的 Header、Payload 和 Signature 如下:Header:
json
{
"alg": "HS256",
"typ": "JWT"
}
Payload:
json
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
Signature:
假设使用密钥 your-256-bit-secret 来生成签名,JWT 会长这样:text
Header: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9
Payload: eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkpvaG4gRG9lIiwgImlhdCI6IDE1MTYyMzkwMjJ9
Signature: 5a91a2098de477b7e3c2a9f507a47f40f2877e75e1f3c3be1e23a1a2da97a73d
完整的 JWT 字符串为:eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkpvaG4gRG9lIiwgImlhdCI6IDE1MTYyMzkwMjJ9.5a91a2098de477b7e3c2a9f507a47f40f2877e75e1f3c3be1e23a1a2da97a73d
这个 JWT 可以作为请求的认证凭证,确保用户身份的安全验证。