JWT(JSON Web Token)是一种用于身份验证和信息交换的紧凑、URL 安全的令牌。JWT 的核心工作原理包括三个主要部分:头部(Header)、载荷(Payload)和签名(Signature)。以下是对 JWT 核心工作原理的详细解释以及在集群环境中如何验证 JWT 的说明。
JWT 核心工作原理
-
头部(Header):
- 头部通常包括令牌类型(即 "JWT")和所使用的签名算法(如 HMAC SHA256 或 RSA)。
- 例如:
{ "alg": "HS256", "typ": "JWT" }
-
载荷(Payload):
- 载荷包含声明(claims),即要传递的用户信息。声明有三种类型:
- 注册声明(Registered claims):一组预定义的声明,不是强制性的,但推荐使用,如
iss
(发行者)、exp
(到期时间)、sub
(主题)、aud
(受众)。 - 公共声明(Public claims):可以由用户定义,但应避免冲突。
- 私有声明(Private claims):自定义的声明,用于信息交换。
- 注册声明(Registered claims):一组预定义的声明,不是强制性的,但推荐使用,如
- 例如:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
- 载荷包含声明(claims),即要传递的用户信息。声明有三种类型:
-
签名(Signature):
- 为了确保令牌的完整性和真实性,JWT 会对头部和载荷进行签名。
- 签名的生成步骤:
- 将头部和载荷分别进行 Base64Url 编码。
- 将编码后的头部和载荷用句点(.)连接起来。
- 使用指定的算法和一个密钥对连接后的字符串进行签名。
- 例如,对于 HMAC SHA256 算法:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
JWT 的生成和验证
-
生成 JWT:
- 服务器在用户登录成功后,创建一个 JWT,包括头部、载荷,并使用密钥签名。
- 生成的 JWT 通过 HTTP 响应返回给客户端。
-
验证 JWT:
- 客户端在后续请求中将 JWT 放在 HTTP 请求头的
Authorization
字段中发送给服务器。 - 服务器接收到请求后,提取 JWT,使用相同的签名算法和密钥验证签名的有效性。
- 如果签名有效且令牌未过期,则允许访问资源。
- 客户端在后续请求中将 JWT 放在 HTTP 请求头的
集群环境中的 JWT 验证
在集群环境中,多个服务实例可能需要验证 JWT。为了实现这一点,通常有以下几种方法:
-
共享密钥:
- 对于对称加密算法(如 HMAC SHA256),所有服务实例共享同一个密钥来签名和验证 JWT。
- 缺点是密钥必须在所有实例之间安全地分发和存储。
-
使用公钥/私钥对:
- 对于非对称加密算法(如 RSA 或 ECDSA),使用私钥签名 JWT,使用公钥验证 JWT。
- 发行者服务持有私钥,签发 JWT。验证者服务持有公钥,验证 JWT。
- 公钥可以公开分发,安全性更高且易于管理。
-
集中认证服务:
- 实现一个专门的认证服务,负责签发和验证 JWT。其他服务在需要时调用该认证服务进行 JWT 验证。
- 这种方法可以集中管理密钥,提高安全性和灵活性,但引入了额外的服务调用开销。
具体实现
共享密钥的示例
假设我们使用对称加密(HMAC SHA256),以下是共享密钥的生成和验证过程:
生成 JWT:
import jwt
import datetime
secret = 'my_secret_key'
payload = {
'sub': '1234567890',
'name': 'John Doe',
'iat': datetime.datetime.utcnow(),
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}
token = jwt.encode(payload, secret, algorithm='HS256')
print(token)
验证 JWT:
import jwt
token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...' # 接收到的 JWT
secret = 'my_secret_key'
try:
decoded_payload = jwt.decode(token, secret, algorithms=['HS256'])
print(decoded_payload)
except jwt.ExpiredSignatureError:
print('Token has expired')
except jwt.InvalidTokenError:
print('Invalid token')
使用公钥/私钥对的示例
假设我们使用非对称加密(RSA),以下是生成和验证 JWT 的过程:
生成 JWT:
import jwt
import datetime
private_key = '''-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA2LV5N2G3F6vA...
-----END RSA PRIVATE KEY-----'''
payload = {
'sub': '1234567890',
'name': 'John Doe',
'iat': datetime.datetime.utcnow(),
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}
token = jwt.encode(payload, private_key, algorithm='RS256')
print(token)
验证 JWT:
import jwt
token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...' # 接收到的 JWT
public_key = '''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...
-----END PUBLIC KEY-----'''
try:
decoded_payload = jwt.decode(token, public_key, algorithms=['RS256'])
print(decoded_payload)
except jwt.ExpiredSignatureError:
print('Token has expired')
except jwt.InvalidTokenError:
print('Invalid token')
结论
JWT 的核心工作原理是通过头部、载荷和签名确保令牌的完整性和安全性。在分布式系统中,可以通过共享密钥或公钥/私钥对实现 JWT 的验证。采用非对称加密时,私钥用于签名,公钥用于验证,这种方式安全性更高且易于管理。集中认证服务也是一种有效的实现方式,但需要权衡性能和安全性。
标签:验证,jwt,JWT,datetime,token,集群,签名 From: https://www.cnblogs.com/gongchengship/p/18284486