5

我正在使用 PyJWT 解码来自 keycloak 的 JWT 令牌。

eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6MWpiUExrTndMVTBkTHk3a0NIT1pyS2FJd3FPMXFrbThDeGtvVHg2QzFBIn0。eyJleHAiOjE2MjE0MjQwMjEsImlhdCI6MTYyMTQyMzk2MSwiYXV0aF90aW1lIjoxNjIxNDIxNzc0LCJqdGkiOiIwYzY2Y2I0My1lMGY1LTQzNjItYTc2MS1lN2M2OWVhNDM5MjUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbIm1hc3Rlci1yZWFsbSIsImFjY291bnQiXSwic3ViIjoiN2Y2ODBlN2MtZGM4Yy00ZGJiLWJiZDEtMTE0ZGJhYjA2Zjc1IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYW11bmRzZW4tZnJvbnRlbmQiLCJzZXNzaW9uX3N0YXRlIjoiYTM5YzJlNmUtZGNjMS00OTM5LTg0ODItYzk2NGE5ODMxNmYyIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJsb2NhbGhvc3Q6NTAwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiY3JlYXRlLXJlYWxtIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsibWFzdGVyLXJlYWxtIjp7InJvbGVzIjpbInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1.aksSjBU5hJ1rtn43NtbMt8E6gaGmJXDrtGDI7j0T7eo6PAcnUxG4spYNNhyksXVr3ZFvua2WyTKnZirqaJUI3zzdLj-XkE7zYCYWoJpjXITmmlj5oszD3pcRdGeyUVyQV49tIiUfUFi1KoIt9K016mH2s_beFrN3TYSjuLh5Epdk_dpNBh9YE_1f3opwsEbN2Jgz_j-VB6cQHq17RzWQIVSd6ZvftAWDWdc6nobOvTy1mZAA_DgsXwdjuNc8Qv36ztuDzkT-raCnuLH479ciBOFQZ0946obIE4ddJKpr7lnVupcbQZ6lDM_QZHz1hwkYqgSU-Ui8NHaWlqt4HJ5-9A

我的代码

import jwt
import traceback


try:
    public_key = """-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhlOIQLHXwZoS3w9SBtvZ1ea4ftWmWnP+HCwlvs7XoJ9EhS+ZQEP7Z25tjW3I8mjUVL0XETrOOjQsD8O2nRBqizJsRaB8L9xsXdJmPHVTx7nphaBPtY5YHxxYqpwEC5rAKtx54YJxw6Ggeicmv+xXtaaDf/VALh5xxpa1U6yP5oqk3yV27yA0beQFVsdugkcfYN0C2FldaUcF9yTUf/KNHTYSu3Ar7iN9U+qEHwaznrLShwh7iknldTKTgEw3liHL8K/5ZlqxHPsL02InwZMaIRic3zNIgVvwedroM6nqZBB4mi1+T0dZn4qsNkG4D0w7IE7MTRgyyYARqrGEq5yOFwIDAQAB
    -----END PUBLIC KEY-----"""

    secret_key = "base-flask-oidc-secret-key"
    token = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6MWpiUExrTndMVTBkTHk3a0NIT1pyS2FJd3FPMXFrbThDeGtvVHg2QzFBIn0.eyJleHAiOjE2MjE0MjQwMjEsImlhdCI6MTYyMTQyMzk2MSwiYXV0aF90aW1lIjoxNjIxNDIxNzc0LCJqdGkiOiIwYzY2Y2I0My1lMGY1LTQzNjItYTc2MS1lN2M2OWVhNDM5MjUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbIm1hc3Rlci1yZWFsbSIsImFjY291bnQiXSwic3ViIjoiN2Y2ODBlN2MtZGM4Yy00ZGJiLWJiZDEtMTE0ZGJhYjA2Zjc1IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYW11bmRzZW4tZnJvbnRlbmQiLCJzZXNzaW9uX3N0YXRlIjoiYTM5YzJlNmUtZGNjMS00OTM5LTg0ODItYzk2NGE5ODMxNmYyIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJsb2NhbGhvc3Q6NTAwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiY3JlYXRlLXJlYWxtIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsibWFzdGVyLXJlYWxtIjp7InJvbGVzIjpbInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiYWRtaW5maXJzdCBhZG1pbmxhc3QiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiJhZG1pbmZpcnN0IiwiZmFtaWx5X25hbWUiOiJhZG1pbmxhc3QiLCJlbWFpbCI6ImFkbWludGVzdEBnbWFpbC5jb20ifQ.aksSjBU5hJ1rtn43NtbMt8E6gaGmJXDrtGDI7j0T7eo6PAcnUxG4spYNNhyksXVr3ZFvua2WyTKnZirqaJUI3zzdLj-XkE7zYCYWoJpjXITmmlj5oszD3pcRdGeyUVyQV49tIiUfUFi1KoIt9K016mH2s_beFrN3TYSjuLh5Epdk_dpNBh9YE_1f3opwsEbN2Jgz_j-VB6cQHq17RzWQIVSd6ZvftAWDWdc6nobOvTy1mZAA_DgsXwdjuNc8Qv36ztuDzkT-raCnuLH479ciBOFQZ0946obIE4ddJKpr7lnVupcbQZ6lDM_QZHz1hwkYqgSU-Ui8NHaWlqt4HJ5-9A"
    # token_json = jwt.decode(token, secret_key, algorithms=['HS256', 'RS256'], audience='account')
    token_json = jwt.decode(token, public_key, algorithms=['HS256', 'RS256'], audience='account')
    print(access_token_json)
    
except Exception:
    print(traceback.print_exc())

根据jwt.io,它显示标题

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "z1jbPLkNwLU0dLy7kCHOZrKaIwqO1qkm8CxkoTx6C1A"
}

我尝试使用公钥和密钥,两者都给我错误

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 232, in _verify_signature
    alg_obj = self._algorithms[alg]
KeyError: 'RS256'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "jwt_test.py", line 16, in <module>
    access_token_json = jwt.decode(access_token, public_key, algorithms=['HS256', 'RS256'], audience='account')
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jwt.py", line 119, in decode
    decoded = self.decode_complete(jwt, key, algorithms, options, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jwt.py", line 95, in decode_complete
    **kwargs,
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 149, in decode_complete
    self._verify_signature(signing_input, header, signature, key, algorithms)
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 239, in _verify_signature
    raise InvalidAlgorithmError("Algorithm not supported")
jwt.exceptions.InvalidAlgorithmError: Algorithm not supported

如果我要从算法列表中删除“RS256”。

token_json = jwt.decode(token, public_key, algorithms=['HS256'], audience='account')

然后我得到错误。

Traceback (most recent call last):
  File "jwt_test.py", line 18, in <module>
    token_json = jwt.decode(token, public_key, algorithms=['HS256'], audience='account')
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jwt.py", line 119, in decode
    decoded = self.decode_complete(jwt, key, algorithms, options, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jwt.py", line 95, in decode_complete
    **kwargs,
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 149, in decode_complete
    self._verify_signature(signing_input, header, signature, key, algorithms)
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 229, in _verify_signature
    raise InvalidAlgorithmError("The specified alg value is not allowed")

我该如何解决这个问题。

提前致谢!

################### 回答 #######################

我能够通过

按照@KlausD 在评论中的建议安装密码学

pip install cryptography

并将公钥更改为

public_key = """-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhlOIQLHXwZoS3w9SBtvZ1ea4ftWmWnP+HCwlvs7XoJ9EhS+ZQEP7Z25tjW3I8mjUVL0XETrOOjQsD8O2nRBqizJsRaB8L9xsXdJmPHVTx7nphaBPtY5YHxxYqpwEC5rAKtx54YJxw6Ggeicmv+xXtaaDf/VALh5xxpa1U6yP5oqk3yV27yA0beQFVsdugkcfYN0C2FldaUcF9yTUf/KNHTYSu3Ar7iN9U+qEHwaznrLShwh7iknldTKTgEw3liHL8K/5ZlqxHPsL02InwZMaIRic3zNIgVvwedroM6nqZBB4mi1+T0dZn4qsNkG4D0w7IE7MTRgyyYARqrGEq5yOFwIDAQAB\n-----END PUBLIC KEY-----"""
4

2 回答 2

8

再次阅读PyJWT 安装指南后,似乎对于某些签名算法,如RSA,需要安装python 密码库。

我通过安装依赖解决了这个问题:

pip install pyjwt[crypto]
于 2021-08-28T18:33:50.170 回答
0

我也遇到了同样的问题(Mac 上的 Python 版本 3.6.7),但解决方案完全不同,我在提供的答案以及其他一些步骤的帮助下解决了这个问题。

注意:不要以为,如果您激活了虚拟环境并长时间保持活动状态,它将按照我们的预期以相同的效率运行。因此,即使您的 PC、笔记本电脑、系统等处于睡眠模式,也要确保重新激活它。

请参阅下面我实际面临的情况并最终解决了问题。

我是如何生成私钥和公钥的?

以下是获取私钥和​​公钥的 2 个命令。

> openssl genrsa -out jwt-key 4096
> openssl rsa -in jwt-key -pubout > jwt-key.pub

获取 JWT(编码)

encoded_jwt = jwt.encode({ "user_id": 1 }, private_key, algorithm='RS256')

在不同虚拟环境的项目中取得了成功。现在我尝试在另一个具有不同虚拟环境的项目中解码这个 JWT(几天前已经激活并且仍然处于活动状态)。

payload = jwt.decode(encoded_jwt, public_key, algorithms=['RS256'])

并看到了这个错误/异常消息。

3.6/site-packages/jwt/api_jws.py", line 226, in _verify_signature
raise InvalidAlgorithmError('Algorithm not supported')
jwt.exceptions.InvalidAlgorithmError: Algorithm not supported

哎呀!让我们尝试解决它!

我是怎么解决的?

阅读答案后,我按照步骤安装pyjwt[crypto]cryptography(其中任何一个)包在我已经激活的虚拟环境中,但我的问题也没有得到解决。这让我考虑尝试另一种算法,但我想尝试并集思广益寻找其他解决方案。

我只是看了一下里面<virtualenv_dir>/lib/site-packages/,发现没有cryptography安装包,而是在实际的 Python 环境中安装在外面。

所以现在,我有一些想法要解决并执行以下步骤来解决问题。

  1. 停用虚拟环境
  2. pip uninstall pyjwt[crypto]
  3. pip uninstall cryptography
  4. 激活虚拟环境
  5. pip install pyjwt[crypto]
  6. pip install cryptography

现在,当我解码编码的 JWT 时,它运行良好。

解码 JWT

> payload = jwt.decode(encoded_jwt, public_key, algorithms=['RS256'])`
> payload
{ "user_id": 1 }

终于,bug解决了。

于 2022-01-23T14:08:27.063 回答