Python JWT库PyJWT使用SHA-256哈希算法在HS256-HMAC上签名时遇到问题

时间:2017-08-02 20:29:48

标签: python jwt pyjwt

尝试使用PyJWT库生成JWT令牌。

当我使用以下程序生成JWT令牌时 - 令牌不起作用。

然而,当我使用具有相同细节的网站https://jwt.io/时,令牌有效。有什么东西我不见了。

我需要python正确生成令牌,这样我就可以自动化一些需要此令牌的API。

Python程序:

import jwt
import base64

code = jwt.encode({'sub':'String','nbf':'1501594247',
                   'exp':'1501767047', 'iss': 'string', 'aud': 'String'},
       base64.b64encode('secret'), algorithm='HS256')
print code

示例:

code = jwt.encode({'sub':'AccountNUmber.QTVR','nbf':'1501594247','exp':'1501860089', 'iss': 'client_id', 'aud': 'https://login.google.com/oauth'},
                  base64.b64encode('secret'), algorithm='HS256')

结果:

  

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjbGllbnRfaWQiLCJhdWQiOiJodHRwczovL2xvZ2luLmdvb2dsZS5jb20vb2F1dGgiLCJzdWIiOiJBY2NvdW50TlVtYmVyLlFUVlIiLCJleHAiOiIxNTAxODYwMDg5IiwibmJmIjoiMTUwMTU5NDI0NyJ9.dRUUQYJ-RmxgoExwPyrvHPzX9SsxcpX1rOWlhisxNsg

https://jwt.io/生成的令牌:

  

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjbGllbnRfaWQiLCJhdWQiOiJodHRwczovL2xvZ2luLmdvb2dsZS5jb20vb2F1dGgiLCJzdWIiOiJBY2NvdW50TlVtYmVyLlFUVlIiLCJleHAiOiIxNTAxODYwMDg5IiwibmJmIjoiMTUwMTU5NDI0NyJ9.INp-ZnnL8Uj7MIwLYmpZtGyTyZG-oqZRNW8iZ145jVs

https://jwt.io/生成的令牌在我调用端点时有效。我得到状态代码200(成功)。

然而,当我使用从我的程序生成的令牌时,它会提供“无效令牌”。 - 400(不良请求)。

2 个答案:

答案 0 :(得分:2)

这里的错误是你的python语句中的base64.b64encode。 在将秘密传递给jwt.encode之前,您不应该对其进行编码。我认为jwt.io调试器在这方面有点误导:

enter image description here

这里的想法是,你有一个以某种方式存储在base64编码格式中的秘密,当你告诉他编码时,jwt.io调试器会解密你的秘密。

您可以轻松查看idle

>>> base64.b64encode('secret')
'c2VjcmV0'

如果您将编码的密码粘贴到jwt.io上的密码字段并选中上图所示的复选框,您将获得以下标记:

  

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjbGllbnRfaWQiLCJhdWQiOiJodHRwczovL2xvZ2luLmdvb2dsZS5jb20vb2F1dGgiLCJzdWIiOiJBY2NvdW50TlVtYmVyLlFUVlIiLCJleHAiOiIxNTAxODYwMDg5IiwibmJmIjoiMTUwMTU5NDI0NyJ9.Nk6oCKBlT9lh4rtJZzF8JuyEsiH_HBaa3UhUx3DbWeI

与以下python程序的输出相同:

a)当你直接提供秘密而不是编码时:

code = jwt.encode({'sub':'AccountNUmber.QTVR','nbf':'1501594247','exp':'1501860089', 'iss': 'client_id', 'aud': 'https://login.google.com/oauth'}, 
                  'secret', algorithm='HS256')

b)当您提供编码密码时:

code = jwt.encode({'sub':'AccountNUmber.QTVR','nbf':'1501594247','exp':'1501860089', 'iss': 'client_id', 'aud': 'https://login.google.com/oauth'},
                  base64.b64decode('c2VjcmV0'), algorithm='HS256')

这应该有效。

答案 1 :(得分:0)

文档中有错误,我检查了该库的源代码

class PyJWT(PyJWS):
    header_type = 'JWT'

    @staticmethod
    def _get_default_options():
        # type: () -> Dict[str, bool]
        return {
            'verify_signature': True,
            'verify_exp': True,
            'verify_nbf': True,
            'verify_iat': True,
            'verify_aud': True,
            'verify_iss': True,
            'require_exp': False,
            'require_iat': False,
            'require_nbf': False
        }

    def encode(self,
               payload,  # type: Union[Dict, bytes]
               key,  # type: str
               algorithm='HS256',  # type: str
               headers=None,  # type: Optional[Dict]
               json_encoder=None  # type: Optional[Callable]
               ):
        # Check that we get a mapping
        if not isinstance(payload, Mapping):
            raise TypeError('Expecting a mapping object, as JWT only supports '
                            'JSON objects as payloads.')

        # Payload
        for time_claim in ['exp', 'iat', 'nbf']:
            # Convert datetime to a intDate value in known time-format claims
            if isinstance(payload.get(time_claim), datetime):
                payload[time_claim] = timegm(payload[time_claim].utctimetuple())  # type: ignore

        json_payload = json.dumps(
            payload,
            separators=(',', ':'),
            cls=json_encoder
        ).encode('utf-8')

        return super(PyJWT, self).encode(
            json_payload, key, algorithm, headers, json_encoder
        )

因此解决方案将

from jwt.api_jwt import PyJWT


payload = {
    'id': 5,
    'email': 'ASDASDA'
}

key = 'secret'

jwt_Obj=PyJWT()
jwt_token = jwt_Obj.encode( payload=payload,key= key )
decode_token=jwt_Obj.decode(jwt_token,key=key)

print (jwt_token)
print(decode_token)

输出应该或(必须)为  b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6IkFTREFTREEiLCJpZCI6NX0.-Woz4Crgi5KZj_D99eGaKxY4VxosY7r_e7HTD9JaDqE'

{'email':'ASDASDA','id':5}