【发布时间】:2019-01-20 18:29:55
【问题描述】:
我有一个用 Python 编写的 API 和另一个用 Ruby 编写的 API。我们需要它们在它们之间发送数据,并决定使用 JWT 作为身份验证方法。基本上在两端生成一个令牌并确保它们匹配。现在我遇到了 python 和 ruby 之间匹配哈希的问题。鉴于此代码:python (2.7) PyJWT == 1.6.4
>>> import jwt
>>> jwt.encode({"someKey":123}, "secret", algorithm='HS256')
u'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lS2V5IjoxMjN9.DL8qyWMeqfMMLCTPN3RA9K08e-AkNW_ybPyywvrIIZ8'
这似乎在 python 版本之间也发生了变化——运行这个作为 python3 产生了这个
b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhcHBlbklkIjoxMjN9.YgFKZePJYMRDMgubCeZBy6WaFKiTA9C-TRnnZLFJC8E'
然后,当我在 ruby 中创建一个类似的“函数”时,我得到一个不同的哈希值 - 这在 ruby 的 jwt 版本之间也是如此(我已经测试过 jwt-1.5.6 和 jwt-2.1.0) - 下面是jwt-1.5.6 结果。
require "jwt"
someKey = 123
secret = "secret"
payload = {"someKey" => someKey}
token = JWT.encode payload, secret, 'HS256'
puts token
该代码的输出是
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lS2V5IjoxMjN9.7Ch3o7IXmxqm79AcrTetXuZv6h3suyLD5_IgXdrRlNs
使用 jwt-2.1.0 版本,我得到:
eyJhbGciOiJIUzI1NiJ9.eyJzb21lS2V5IjoxMjN9.QkKm2IuvOz_D5ukIxOsjMYApzV2ZnjLE2HII3ZfP_hsWith
为什么这两个代码集的输出会产生两个不同的哈希值?
编辑: 当我使用 jwt.io 时
我得到与 python 相同的令牌
【问题讨论】:
-
jwt 1.5.6 和 jwt 2.1.0 是否使用相同的哈希函数?您是否在散列相同的数据(python 中的字典不是 JSON)?有趣的问题,但从设计的角度来看,你可能不应该这样做:)
-
您只能在 python 端使用 dict(jwt.encode 只接受 dicts) - 但对于 Ruby 端,该函数接受 dict 或 JSON 字符串 - 两者都不匹配。
-
没怎么看代码,但是Python3中默认切换为Unicode字符串,Python2中不是这样。这会导致不同的输出吗?使用 Python2 将
u添加到字符串中,然后查看输出是否匹配。 -
如果您检查 JWT.io 上的所有 JWT,您会看到不同的标头字段顺序(但值相同),只有第二个 ruby 示例缺少
typ标头。有效载荷是"someKey":"123",但在python3中它改为"appenId":"123"。难怪结果不一样。 JWT 的想法不是生成相同的令牌来比较它们,而是拥有一个签名,使您能够验证令牌本身。