JWT 的核心工作原理是什么?集群中的其他 服务如何验证这个JWT 呢?

JWT(JSON Web Token)是一种用于身份验证和信息交换的紧凑、URL 安全的令牌。JWT 的核心工作原理包括三个主要部分:头部(Header)、载荷(Payload)和签名(Signature)。以下是对 JWT 核心工作原理的详细解释以及在集群环境中如何验证 JWT 的说明。

JWT 核心工作原理

  1. 头部(Header)

    • 头部通常包括令牌类型(即 "JWT")和所使用的签名算法(如 HMAC SHA256 或 RSA)。
    • 例如:
      {
        "alg": "HS256",
        "typ": "JWT"
      }
      
  2. 载荷(Payload)

    • 载荷包含声明(claims),即要传递的用户信息。声明有三种类型:
      • 注册声明(Registered claims):一组预定义的声明,不是强制性的,但推荐使用,如 iss(发行者)、exp(到期时间)、sub(主题)、aud(受众)。
      • 公共声明(Public claims):可以由用户定义,但应避免冲突。
      • 私有声明(Private claims):自定义的声明,用于信息交换。
    • 例如:
      {
        "sub": "1234567890",
        "name": "John Doe",
        "admin": true
      }
      
  3. 签名(Signature)

    • 为了确保令牌的完整性和真实性,JWT 会对头部和载荷进行签名。
    • 签名的生成步骤:
      1. 将头部和载荷分别进行 Base64Url 编码。
      2. 将编码后的头部和载荷用句点(.)连接起来。
      3. 使用指定的算法和一个密钥对连接后的字符串进行签名。
    • 例如,对于 HMAC SHA256 算法:
      HMACSHA256(
        base64UrlEncode(header) + "." + base64UrlEncode(payload),
        secret
      )
      

JWT 的生成和验证

  1. 生成 JWT

    • 服务器在用户登录成功后,创建一个 JWT,包括头部、载荷,并使用密钥签名。
    • 生成的 JWT 通过 HTTP 响应返回给客户端。
  2. 验证 JWT

    • 客户端在后续请求中将 JWT 放在 HTTP 请求头的 Authorization 字段中发送给服务器。
    • 服务器接收到请求后,提取 JWT,使用相同的签名算法和密钥验证签名的有效性。
    • 如果签名有效且令牌未过期,则允许访问资源。

集群环境中的 JWT 验证

在集群环境中,多个服务实例可能需要验证 JWT。为了实现这一点,通常有以下几种方法:

  1. 共享密钥

    • 对于对称加密算法(如 HMAC SHA256),所有服务实例共享同一个密钥来签名和验证 JWT。
    • 缺点是密钥必须在所有实例之间安全地分发和存储。
  2. 使用公钥/私钥对

    • 对于非对称加密算法(如 RSA 或 ECDSA),使用私钥签名 JWT,使用公钥验证 JWT。
    • 发行者服务持有私钥,签发 JWT。验证者服务持有公钥,验证 JWT。
    • 公钥可以公开分发,安全性更高且易于管理。
  3. 集中认证服务

    • 实现一个专门的认证服务,负责签发和验证 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 的验证。采用非对称加密时,私钥用于签名,公钥用于验证,这种方式安全性更高且易于管理。集中认证服务也是一种有效的实现方式,但需要权衡性能和安全性。

posted @   gongchengship  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示