1

以下 python 代码使用以下代码生成有效的 JWT 令牌pyjwt

>>> import jwt
>>> payload = {'nested': [{'name': 'me', 'id': '1'}]}
>>> token = jwt.encode(payload, 'secret')
>>> token.decode()
ey[...]ko0Zq_k

pyjwt还支持从命令行界面调用。但是文档只显示了具有=分离键值对的示例,而不是嵌套有效负载的示例。

我最好的猜测是这样的:

$ pyjwt --key=secret encode nested=[{name=me, id=1}]
ey[...]0FRW9gyU  # not the same token as above :(

这没有用。它根本不支持吗?

4

1 回答 1

1

如前所述,您的命令行令牌在解码时会返回此json对象:

{'nested': '[{name=me,', 'id': '1}]'}

快速浏览__main__.pyofjwt包给出了这个小片段:

... snipped

def encode_payload(args):
    # Try to encode
    if args.key is None:
        raise ValueError('Key is required when encoding. See --help for usage.')

    # Build payload object to encode
    payload = {}

    for arg in args.payload:
        k, v = arg.split('=', 1)

    ... some additional handling on v for time, int, float and True/False/None
    ... snipped

如您所见,有效负载的键和值是直接基于 确定的split('=', 1),因此=在您的命令行中通过第一个键后传递的任何内容将始终被确定为单个值(之后进行一些转换)。

所以简而言之,不支持 CLI 中的嵌套dicts 。

然而,半好消息是,有一些方法可以解决这些问题:

  1. 像这样直接在 Python 的 CLI 上运行即兴语句:

    > python -c "import jwt; print(jwt.encode({'nested':[{'name':'me', 'id':'1'}]}, 'secret').decode('utf-8'))"
    
    # eyJ...Zq_k
    

不完全理想,但它可以满足您的需求。

  1. 将相同的脚本保存到能够接受 args 的 .py 中并在 Python 的 CLI 上执行它:

    import sys, jwt
    my_json = sys.argv[0]
    token = jwt.encode(eval(my_json), 'secret')
    print(token.decode('utf-8'))
    
    # run in CLI
    > python my_encode.py "{'nested':[{'name':'me', 'id':'1'}]}"
    
    # eyJ...Zq_k
    

请注意,出于安全考虑,eval()此处的使用并不理想。这只是我实现它的懒惰方式,因为我不想为 args 编写解析器。如果您绝对必须在实现中使用 CLI 并且它已经暴露出来,我强烈建议您将精力投入到argv更仔细地清理和解析 s 上。

  1. 最人为的方法:您可以尝试修改Lib\site-packages\jwt\__main__.py功能(后果自负)以满足您的需要,直到添加官方支持。我提醒您,在考虑弄乱主代码之前,您应该对编写自己的解析感到相当自在。在意识到您将遇到的限制之前,我尝试了一些尝试:

    一个。mainencode()方法不将 alist视为有效的 JSON 对象(但它应该)。所以马上你必须有一个dict类似的字符串来操作。

    湾。代码总是强制数字尽可能intfloat如果可能的话。您需要以某种方式或完全改变它处理数字的方式来逃避它。

    我的尝试是这样的:

    def func(result, payload):
        for arg in payload:
            k, v = arg.split('=', 1)
    
            if v.startswith('{') and v.endswith('}'):
                result[k] = func({}, v[1:-1])
            else:
            ... the rest of the existing code
    

    但是我很快就遇到了原始参数已经用空格分隔的限制,并假设它是一对kv我需要进一步处理另一个分隔符,比如,处理lists 的能力,它可能会变得更加混乱。这绝对是可行的,而且效果立竿见影,即 CLI 直接从 this 中运行__main__.py,但它的工作量比我现在想投资的要多,所以我把它交给你有能力的人。

克服这些问题以实现您所需要的努力可能是不必要的,这取决于您的技能和舒适度。所以选择你的战斗......如果 CLI 不是绝对必要的,我建议只使用这些.py方法。

于 2018-10-30T14:38:31.123 回答