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__.pyofパッケージに簡単に飛び込むと、次のjwt小さなスニペットが得られます。

... 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. 同じスクリプトを、引数を取ることができる .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()ここでの使用は理想的ではないことに注意してください。引数のパーサーを書きたくないので、これは私の怠惰な実装方法です。argv実装に CLI を絶対に使用する必要があり、それが公開されている場合は、より慎重に s のクレンジングと解析に労力を費やすことを強くお勧めします。

  1. 最も不自然な方法:公式サポートが追加されるまで、必要に応じて (自己責任で) 関数を変更してみてください。Lib\site-packages\jwt\__main__.pyただし、メイン コードをいじることを検討する前に、独自の解析を作成することに慣れている必要があることに注意してください。あなたが遭遇する制限に気付く前に、私はそれをいくつか突き刺しました:

    を。mainメソッドはa を有効な JSON オブジェクトencode()と見なしません(ただし、そうすべきです)。listしたがって、すぐdictに操作する文字列が必要です。

    b. intこのコードは常に、float可能であれば数値を強制的にキャストします。何らかの方法でエスケープするか、数値の処理方法を完全に変更する必要があります。

    私の試みは次のようになりました:

    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
    

    ただし、元の引数が既にスペースで区切られているという制限にすぐに遭遇し、それがk, のペアであると仮定すると、 sを処理する機能だけでなく、v別の区切り記号をさらに処理する必要があり、より厄介になる可能性があります。それは間違いなく実行可能であり、効果はすぐに得られます。つまり、CLI は this から直接実行されますが、現時点で投資したい以上の作業であるため、有能な手に委ねます。,list__main__.py

これらの問題を克服して必要なものを達成するための努力は、スキルと快適さのレベルに応じて、必要以上になる場合があります. だからあなたの戦いを選んでください... CLIが絶対に必要でない場合は、.py代わりにメソッドを使用することをお勧めします.

于 2018-10-30T14:38:31.123 に答える