Python 3.7中修改JWT头部顺序?PyJWT头部顺序不符问题求解
这个问题我之前也碰到过!PyJWT默认会对JWT头部的键按字母顺序排序,所以生成的是typ在前、alg在后的结构,但目标JWT的字段顺序反过来,导致签名验证失败——毕竟JWT的签名是基于头部和Payload的Base64编码拼接后的内容,字段顺序不同的话,Base64结果完全不一样,签名自然对不上。
下面给你两种可行的解决方案:
方案一:利用PyJWT自带参数控制头部顺序
如果你用的是PyJWT 2.0+版本(建议升级到最新版),可以通过json_kwargs参数关闭键排序,同时自定义头部的字段顺序:
import jwt import json payload = {'some': 'payload'} secret = 'secret' # 按我们需要的顺序定义头部字典(Python3.7+字典默认保留插入顺序) custom_headers = {'alg': 'HS512', 'typ': 'JWT'} # 生成符合要求的JWT token = jwt.encode( payload, secret, algorithm='HS512', headers=custom_headers, json_kwargs={'sort_keys': False} ) print(token) # 生成的token解码后头部会是 {"alg":"HS512","typ":"JWT"}
这里的json_kwargs={'sort_keys': False}会传递给底层的json.dumps方法,告诉序列化器不要对字典键进行排序,从而严格保留我们定义的头部字段顺序。
方案二:手动构造JWT(完全可控)
如果你的PyJWT版本较旧,或者需要更精细的控制,可以完全手动实现JWT的生成流程,彻底绕过PyJWT的默认逻辑:
import base64 import hashlib import hmac import json def generate_jwt_with_custom_header_order(payload, secret, algorithm='HS512'): # 1. 构造并序列化头部,严格控制字段顺序 header = {'alg': algorithm, 'typ': 'JWT'} # 使用separators去掉空格,符合JWT的紧凑格式要求 header_json = json.dumps(header, separators=(',', ':'), sort_keys=False).encode('utf-8') # URL安全Base64编码,移除末尾的=符号 header_b64 = base64.urlsafe_b64encode(header_json).rstrip(b'=').decode('utf-8') # 2. 序列化Payload(如果需要也可以控制顺序,一般Payload顺序不影响签名验证) payload_json = json.dumps(payload, separators=(',', ':'), sort_keys=False).encode('utf-8') payload_b64 = base64.urlsafe_b64encode(payload_json).rstrip(b'=').decode('utf-8') # 3. 计算HS512签名 signing_input = f"{header_b64}.{payload_b64}".encode('utf-8') if algorithm == 'HS512': signature = hmac.new(secret.encode('utf-8'), signing_input, hashlib.sha512).digest() else: raise ValueError(f"暂不支持该算法:{algorithm}") signature_b64 = base64.urlsafe_b64encode(signature).rstrip(b'=').decode('utf-8') # 4. 拼接成最终JWT return f"{header_b64}.{payload_b64}.{signature_b64}" # 使用示例 token = generate_jwt_with_custom_header_order({'some': 'payload'}, 'secret', 'HS512') print(token)
这种方法完全由你掌控每一步的处理逻辑,头部顺序绝对不会出现偏差,适合需要高度定制的场景。
内容的提问来源于stack exchange,提问作者user10243206
相关产品推荐
相关产品推荐

