不同的服务器使用相同的参数生成不同的 JWT 令牌

Posted

技术标签:

【中文标题】不同的服务器使用相同的参数生成不同的 JWT 令牌【英文标题】:Different servers generate different JWT tokens using the same parameters 【发布时间】:2017-09-07 03:59:07 【问题描述】:

我正在使用python-jose 的 JWT 实现来生成用于身份验证的 JWT 令牌。

我们在 Kubernetes 上的 Docker 容器中运行我们的后端,有时,当我们有多个 pod 时,我们会为相同的声明、秘密和算法获得不同的令牌 .当touching 我的index.wsgi 脚本时,我的开发环境中的单个容器上也发生了这种情况。

吊舱 1:

>>> jwt.encode('key': 'value', 'secret', algorithm='HS256')
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ2YWx1ZSJ9.FG-8UppwHaFp1LgRYQQeS6EDQF7_6-bMFegNucHjmWg'

吊舱 2:

>>> jwt.encode('key': 'value', 'secret', algorithm='HS256')
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJ2YWx1ZSJ9.JPIDicqvQ6GAh14yE2yZ3wnZQ0LiLNTTRDtJgLZcn98'

我深入研究了代码以查看可能导致此问题的原因,但没有发现任何有罪的地方。简而言之,代码的作用如下:

    对算法头 ('typ': 'JWT', 'alg': 'HS256') 做一个 json.dumps 并将其编码为 Base64,删除任何 = 的 对有效载荷 ('key': 'value') 执行 json.dumps 并将其编码为 Base64,删除任何 = 使用带有secret 密钥的HMAC256 签名encoded_header.encoded_payload 并将其编码为Base64,再次删除任何= 的 将签名连接到前一个字符串,得到encoded_header.encoded_payload.encoded_signature

目前,我不知道是什么原因造成的。我怀疑 Python 的 HMAC 或 SHA256 实现中存在某种错误,但这似乎不太可能......有任何线索吗?

注意:我们已经成功重现了 pyjwt 的错误,这是 python-jose 的基础。

【问题讨论】:

【参考方案1】:

这是因为 Python 字典是无序的。如果您对这两个 JWT 进行解码,您将看到每个令牌的标头部分的顺序不同。


    "typ": "JWT",
    "alg": "HS256"


    "alg": "HS256",
    "typ": "JWT"

这会导致base64编码的header不同,进而导致签名不同。

也就是说,对于完全相同的声明集,这两个都是有效令牌,并且都应该成功验证。 JWT 规范中没有任何内容规定等效的声明集应该产生等效的 JWT 输出。

注意:我是python-jose 库的作者。

【讨论】:

为找到丢失的部分而欢呼。这不是 JWT 本身的问题,而是我使用它的方式的问题。根据我读过的内容,我认为保存和剥离标题部分会很整洁,因为它应该是恒定的。基本上,我通过编码任意有效载荷并提取标头来生成FIXED_HEADER。然后,生成的令牌将在返回之前从它们的标题中剥离,然后我会在解码之前再次添加它。这导致签名验证失败的原因现在很明显了。不再剥离标题。

以上是关于不同的服务器使用相同的参数生成不同的 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章

在多个服务中处理 JWT 令牌

JWT认证方案与禁用令牌策略

JWT:多客户端身份验证服务器,停止在不同客户端之间使用 jwt?

刷新令牌和 JWT 令牌交互

JWT 可以跨不同的 AngularJS 应用程序使用吗?

如何识别来自不同租户nestjs多租户jwt的jwt令牌