JWT的生成和工作原理
深入了解 JWT(JSON Web Token)
在现代 Web 应用和分布式系统中,身份验证和授权是两个关键的部分。为了应对这些需求,JWT(JSON Web Token) 应运而生。它作为一种紧凑的、安全的、URL 安全的令牌格式,广泛应用于身份验证和信息交换中。本文将深入探讨 JWT 的结构、工作原理、优缺点以及常见的应用场景,帮助你更好地理解并运用 JWT。
什么是 JWT?
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间以 JSON 对象的形式安全地传递信息。JWT 主要由三部分组成:
- 头部(Header)
- 载荷(Payload)
- 签名(Signature)
这些部分通过 Base64 URL 编码 后组合在一起,形成一个完整的 JWT Token,通常用于 身份验证 和 信息交换。
JWT 的结构
JWT 的结构是由三部分组成,并通过点(.
)连接在一起:
<Header>.<Payload>.<Signature>
1. Header(头部)
头部通常包含两部分信息:
alg
(算法):指定签名使用的算法,比如 HMAC SHA256(HS256
)或 RSA(RS256
)。typ
(类型):通常是JWT
,表示这是一个 JSON Web Token。
示例:
{"alg": "HS256","typ": "JWT"
}
编码后的 Header
部分会是:
eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9
2. Payload(载荷)
Payload 部分包含 JWT 的 声明(Claims)。声明是关于实体(通常是用户)及其他数据的声明。JWT 有三种类型的声明:
- 注册声明(Registered Claims):这些是 JWT 预定义的标准声明,如
sub
(主题)、iat
(签发时间)、exp
(过期时间)、aud
(受众)等。 - 公共声明(Public Claims):可以自定义,避免与其他人冲突。
- 私有声明(Private Claims):由使用者自定义,适用于在两方之间传递信息。
示例:
{"sub": "1234567890","name": "John Doe","iat": 1516239022
}
编码后的 Payload
部分会是:
eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkpvaG4gRG9lIiwgImlhdCI6IDE1MTYyMzkwMjJ9
3. Signature(签名)
签名用于确保消息的完整性,并验证发送者的身份。为了生成签名,你需要知道密钥,并选择一种签名算法(如 HMAC SHA256)。签名的生成过程如下:
- 将
Header
和Payload
使用 Base64 URL 编码。 - 使用密钥和签名算法(如
HS256
)对Header
和Payload
拼接的结果进行签名。
签名的计算公式:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)
示例签名:
f1f99fa2445973487d469b1b3e4b38c53a8c9c8fa55e3e08e52a970e9cfbce18
最终生成的完整 JWT 会是:
eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkpvaG4gRG9lIiwgImlhdCI6IDE1MTYyMzkwMjJ9.f1f99fa2445973487d469b1b3e4b38c53a8c9c8fa55e3e08e52a970e9cfbce18
例子:
1. jwt生成
import jwt
import time# 定义头部信息
header = {"alg": "HS256","typ": "JWT"
}# 定义载荷信息(与提供的相同的时间戳等信息)
payload = {"username": "www.json.cn","sub": "demo","iat": 1735033926, # 签发时间"nbf": 1735033926, # 生效时间"exp": 1735120326 # 过期时间
}# 对称密钥
secret_key = "json.cn"# 生成JWT Token
encoded_jwt = jwt.encode(payload, secret_key, algorithm="HS256", headers=header)# 输出生成的JWT Token
print("Generated JWT Token:", encoded_jwt)# 如果需要验证JWT Token是否有效
decoded_jwt = jwt.decode(encoded_jwt, secret_key, algorithms=["HS256"])
print("Decoded JWT:", decoded_jwt)
2. 手动生成
import base64
import json
import hashlib
import hmac# 头部信息
header = {"alg": "HS256","typ": "JWT"
}# 载荷信息
payload = {"username": "www.json.cn","sub": "demo","iat": 1735035050,"nbf": 1735035050,"exp": 1735121450
}# 密钥
secret_key = "json.cn"# 生成 JWT
def encode_jwt(header, payload, secret_key):# Base64 URL 编码函数def base64_url_encode(data):return base64.urlsafe_b64encode(data).rstrip(b'=')# 将头部和载荷转换为 JSON 字符串header_json = json.dumps(header, separators=(',', ':')).encode('utf-8')payload_json = json.dumps(payload, separators=(',', ':')).encode('utf-8')# Base64 URL 编码头部和载荷header_b64 = base64_url_encode(header_json)payload_b64 = base64_url_encode(payload_json)# 创建签名message = header_b64 + b"." + payload_b64signature = hmac.new(secret_key.encode('utf-8'), message, hashlib.sha256).digest()# Base64 URL 编码签名signature_b64 = base64_url_encode(signature)# 拼接最终的 JWTjwt_token = header_b64 + b"." + payload_b64 + b"." + signature_b64return jwt_token.decode('utf-8')# 生成 JWT Token
jwt_token = encode_jwt(header, payload, secret_key)print(jwt_token)
jwt源码实现:
1. 进到编码方法
2. 序列化payload
3. 执行父类方法 序列法header
4. 等于号别替换成了空
5. 返回签名
JWT 工作原理
JWT 的工作原理主要分为三个阶段:生成、传输 和 验证。
1. JWT 生成
- 用户登录时,服务器验证用户的凭证(如用户名和密码)。如果凭证有效,服务器会生成一个 JWT。
- 服务器将用户的信息(如用户 ID、角色等)作为载荷放入 JWT 中。然后,使用密钥对 JWT 进行签名,确保其安全性和完整性。
- 生成的 JWT 会发送给用户,通常通过 HTTP 头部传递。
2. JWT 传输
生成的 JWT 会在后续的请求中传递给服务器。最常见的传输方式是将 JWT 放在 Authorization Header 中,使用 Bearer
方案:
Authorization: Bearer <JWT>
JWT 也可以存储在 Cookies 中。
3. JWT 验证
当客户端发起请求时,JWT 会被包含在请求头或 Cookies 中,服务器接收到 JWT 后进行以下验证:
- 解码:服务器解析 JWT,并分离出
Header
、Payload
和Signature
。 - 验证签名:服务器使用密钥验证签名,确保数据未被篡改。
- 验证过期时间:如果 JWT 包含
exp
(过期时间)声明,服务器会检查当前时间是否在有效期内。
JWT 的优缺点
优点
- 无状态:JWT 是自包含的,它不依赖于服务器端的会话存储,因此服务器不需要维护用户的会话状态,减轻了服务器负担。
- 跨平台支持:JWT 是 JSON 格式,易于解析,且能在不同的编程语言之间传递。
- 适用于分布式系统:因为它不依赖服务器存储,JWT 非常适合微服务架构等分布式系统。
- 灵活性高:JWT 可以存储多种类型的声明,可以扩展和定制。
缺点
- 不可撤销性:一旦 JWT 被签发,它就无法撤销,除非在服务器端维护一个黑名单,这对长时间使用的令牌可能会造成一定问题。
- 安全性:如果签名密钥泄露,攻击者可以伪造 JWT。为了保障安全性,必须使用强大的密钥,并且定期更新。
- Token 大小:虽然 JWT 是自包含的,但它的大小比传统的 Session ID 大,尤其是在存储大量信息时,可能会影响请求的效率。
JWT 的常见应用场景
JWT 主要用于以下几个场景:
1. 身份验证(Authentication)
最常见的应用场景是身份验证。用户登录后,服务器生成 JWT 令牌,并将其返回给客户端。客户端在之后的请求中使用该 JWT 令牌进行身份验证,而不需要每次都发送用户名和密码。
2. 授权(Authorization)
JWT 还可以用来进行授权。在请求中,JWT 会携带用户的身份信息和权限,服务器可以根据这些信息判断用户是否有权限访问特定资源。
3. 信息交换(Information Exchange)
JWT 也常用于在不同系统间交换信息,特别是当需要保证数据的完整性和不可篡改时。由于 JWT 可以被签名,它提供了一个可靠的机制来验证数据来源的真实性。
总结
JWT 是一种非常流行且强大的身份验证与信息交换标准。它具有自包含、无状态等特点,适合分布式系统和微服务架构的应用。然而,在使用 JWT 时,必须注意密钥的安全性、令牌的过期时间以及不可撤销性等问题。了解 JWT 的结构和工作原理,将帮助你在实际开发中更好地运用它,提升应用的安全性与可扩展性。