pyjwt接入苹果登录
流程图

测试代码:
#coding=utf-8 import jwt import requests from datetime import datetime, timedelta import random import json ''' kty:常量标识使用RSA签名算法 kid:密钥id标识 alg:签名算法采用的是RS256(RSA 256 + SHA 256) n/e:公钥参数,其值采用BASE64编码,使用时需要先解码 完整的payload字符串为: { "iss": "https://appleid.apple.com", "aud": "com.aaaaa.bbbbb", "exp": 1692757384, "iat": 1692670984, "sub": "000942.2a81a3fedeaaaaaaa2179fa9b30b2.0223", "c_hash": "BJBc4awcx1pCt6OF9Czp9g", "email": "qz2bbjwffd@privaterelay.appleid.com", "email_verified": "true", "is_private_email": "true", "auth_time": 1692670984, "nonce_supported": true, "real_user_status": 2 } ''' ''' # 创建 JWT encoded_jwt = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256') print(encoded_jwt) # 解码 JWT decoded_jwt = jwt.decode(encoded_jwt, 'secret', algorithms=['HS256']) print(decoded_jwt) ''' # Apple 的公钥服务器地址 APPLE_PUBLIC_KEY_URL = "https://appleid.apple.com/auth/keys" def jsonStandFormat(jsondata): return json.dumps(jsondata, sort_keys=True, indent=4, separators=(',', ':'), ensure_ascii=False) #从token中获取kid def get_token_kid(token): headers = jwt.get_unverified_header(token) kid = headers.get('kid', '') print('headers: ') print(jsonStandFormat(headers)) print('') return kid #从Apple 获取公钥列表 def get_apple_public_keys(): response = requests.get(APPLE_PUBLIC_KEY_URL) response.raise_for_status() # 确保请求成功 results = response.json()['keys'] print('keys: ') print(jsonStandFormat(results)) print('') return results #根据token中的kid获取公钥信息 def get_apple_public_key(keys, kid): # 选择一个有效的公钥,通常是最近的一个,这里简单取第一个,实际应用中可能需要更复杂的逻辑 result = [keys[0]['kid'], keys[0]['n'], keys[0]['e']] for i, key in enumerate(keys): if key['kid'] == kid: result = [keys[i]['kid'], keys[i]['n'], keys[i]['e']] break; print('key: ') print(jsonStandFormat(result)) print('') return result #验证JWT令牌 def verify_jwt(token): kid = get_token_kid(token) keys = get_apple_public_keys() kid, n, e = get_apple_public_key(keys, kid) public_key = "-----BEGIN PUBLIC KEY-----\n%s\n%s\n-----END PUBLIC KEY-----" % (n, e) print(public_key) print('') options = { "verify_exp": False, "verify_iat": False, "verify_aud": False, "verify_signature": False } try: decoded = jwt.decode(token, public_key, algorithms=['RS256'], options=options) # verify_aud 根据你的配置设置 return decoded except jwt.ExpiredSignatureError: print('Token已过期') except jwt.InvalidAudienceError: print('错误的audience') except jwt.InvalidIssuerError: print('错误的issuer') except jwt.InvalidTokenError: print('无效Token') except Exception as e: print("Token解码失败") print(e) return None #使用示例 token = "eyJraWQiOiJmaDZCczhDIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLnRqZ2QuZGV2ZWxvcC5tb2JpbGV6Lldpc2VUViIsImV4cCI6MTY5MTY0Mzc3MSwiaWF0IjoxNjkxNTU3MzcxLCJzdWIiOiIwMDA0NDAuM2E5M2Y3MDY1NTE0NGY5Mjg5ZGJlY2Q2ODhhMmQxNzguMDc0NSIsImNfaGFzaCI6IjkyOEVmVEliSkVVUDBVQlhNRF9wZHciLCJlbWFpbCI6InRqZ2RpcHR2QGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoidHJ1ZSIsImF1dGhfdGltZSI6MTY5MTU1NzM3MSwibm9uY2Vfc3VwcG9ydGVkIjp0cnVlfQ.gt1DjUwX5oAzmYyoVoFtqjWv8D3SXkBm327RnadilOQxYbLLM82l45EWozjykRMhMtH4bWsP47m6DtBvwfA13kQg9HNTFCYOdm7j2SnF_3S5m_6sHvaxkK0VDbuk3Z-aWOcMlHMj4kFOdM9EMC5-1Qr_k9y6i7RRmh_xkAoapoFwSlLCb41J9qnornTbZnRT3CMgMngY90uxvlowYj38YpFW5Q1YDEQVtpDTz55yVIN7yPZ5bUlOHgj2wFWp_2IVo2qKCVgC4-qtoxsRDlR_Wghmv5lh_uwMGAkwBcsTS0eP0fGuYPNoZYuYzpiaLV9j3v01N191xgfUzKVa584Zeg" # 从客户端获取的 JWT 令牌 token_decoded = verify_jwt(token) print('body: ') print(jsonStandFormat(token_decoded)) print('')
输出:
D:\software\Python27\lib\site-packages\jwt\utils.py:8: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in the next release. from cryptography.hazmat.primitives.asymmetric.utils import ( headers: { "alg":"RS256", "kid":"fh6Bs8C" } keys: [ { "alg":"RS256", "e":"AQAB", "kid":"E6q83RB15n", "kty":"RSA", "n":"qD2kjZNSBESRVJksHHnDpMPprhCymecPO8Ji6xlY_fGdUOioVf0nckGaiBwjPGo3xKadAGvbNJ1BjCZOmbLL7lQ5mT8fI6l5HaY8txcz3_PjOUHdiXBuThmQ2eEXtmOtRxi3LNnXaOCpl7QxHgyiPTVgJpJ18Teqz2ESVXg_Lpmw7ot3zBI0p9E56-HVZwxpwS8EoN53nx850fxAlpZj5d1szgV8YzhcRG-8FMOialu-me0OFZWghB-_jCMfdBhWHMWpGkfLPDA1o8eLkr0UByZwMHKCWA--JUvlKvSv3xavDD7ILj8t5PiItonVV9telbza-ToaOWMiG5gZ5QfWDQ", "use":"sig" }, { "alg":"RS256", "e":"AQAB", "kid":"Sf2lFqwkpX", "kty":"RSA", "n":"oNe3ZKHU5-fnmbjhCamUpBSyLkR4jbQy-PCZU4cr7tyPcFokyZ1CjSGm44sw3EPONWO6bWgKZYBX2UPv7UM3GBIuB8qBkkN0_vu0Kdr8KUWJ-6m9fnKgceDil4K4TsSS8Owe9qnP9XjjmVRK7cCEjew4GYqQ7gRcHUjIQ-PrKkNBOOijxLlwckeQK2IN9WS_CBXVMleXLutfYAHpwr2KoAmt5BQvPFqBegozHaTc2UvarcUPKMrl-sjY_AXobH7NjqfbBLRJLzS2EzE4y865QiBpwwdhlK4ZQ3g1DCV57BDKvoBX0guCDNSFvoPuIjMmTxZEUbwrJ1CQ4Ib5j4VCkQ", "use":"sig" }, { "alg":"RS256", "e":"AQAB", "kid":"UaIIFY2fW4", "kty":"RSA", "n":"sxzLtSWjplO4nMymVwkknn6WrQvK4sz7F1rrIwOKPa3SpltaB719cfxFfoE4UqHfVxHXsoYew82ViYz5whp0CuqgWi2t4HYpSTCQdVCNIXpsMxA8QqTfIlc-EUFNuUMziY-hJXqi4i-woI0HiwPEkO-AhWy86L9-J_1I1yw22-BICacAU7J9UTBBwHu0wkRHiyPe4pHow1wa91v5OM09XHqjHpiFrJD7bOBl6Y3EuBXEWy3VEA-S2IchqVGmvNGNZo6J9WtSHEcL6ussFWPJoIo2GR4BrgHvZGUvhgbHrKjCPrIAhliH0er3pF5_0UTSqW0Xg_Q2iQpxo9TRn-kHpw", "use":"sig" } ] key: [ "E6q83RB15n", "qD2kjZNSBESRVJksHHnDpMPprhCymecPO8Ji6xlY_fGdUOioVf0nckGaiBwjPGo3xKadAGvbNJ1BjCZOmbLL7lQ5mT8fI6l5HaY8txcz3_PjOUHdiXBuThmQ2eEXtmOtRxi3LNnXaOCpl7QxHgyiPTVgJpJ18Teqz2ESVXg_Lpmw7ot3zBI0p9E56-HVZwxpwS8EoN53nx850fxAlpZj5d1szgV8YzhcRG-8FMOialu-me0OFZWghB-_jCMfdBhWHMWpGkfLPDA1o8eLkr0UByZwMHKCWA--JUvlKvSv3xavDD7ILj8t5PiItonVV9telbza-ToaOWMiG5gZ5QfWDQ", "AQAB" ] -----BEGIN PUBLIC KEY----- qD2kjZNSBESRVJksHHnDpMPprhCymecPO8Ji6xlY_fGdUOioVf0nckGaiBwjPGo3xKadAGvbNJ1BjCZOmbLL7lQ5mT8fI6l5HaY8txcz3_PjOUHdiXBuThmQ2eEXtmOtRxi3LNnXaOCpl7QxHgyiPTVgJpJ18Teqz2ESVXg_Lpmw7ot3zBI0p9E56-HVZwxpwS8EoN53nx850fxAlpZj5d1szgV8YzhcRG-8FMOialu-me0OFZWghB-_jCMfdBhWHMWpGkfLPDA1o8eLkr0UByZwMHKCWA--JUvlKvSv3xavDD7ILj8t5PiItonVV9telbza-ToaOWMiG5gZ5QfWDQ AQAB -----END PUBLIC KEY----- body: { "aud":"com.tjgd.develop.mobilez.WiseTV", "auth_time":1691557371, "c_hash":"928EfTIbJEUP0UBXMD_pdw", "email":"tjgdiptv@gmail.com", "email_verified":"true", "exp":1691643771, "iat":1691557371, "iss":"https://appleid.apple.com", "nonce_supported":true, "sub":"000440.3a93f70655144f9289dbecd688a2d178.0745" }
参考:
https://huaweicloud.csdn.net/64eea46cc70554103b8eafb7.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NjMzNDQ3LCJleHAiOjE3NTQzODk0NTQsImlhdCI6MTc1Mzc4NDY1NCwidXNlcm5hbWUiOiJ3ZWl4aW5fNDQyMDY5OTMifQ.kYZhDyXAGM8HjJUeIXxyq686W1IPPKopJUhK4yzEak0&spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-4-106122067-blog-147565203.235%5Ev43%5Econtrol&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-4-106122067-blog-147565203.235%5Ev43%5Econtrol&utm_relevant_index=9
https://pyjwt.readthedocs.io/en/stable/
本文来自博客园,作者:河北大学-徐小波,转载请注明原文链接:https://www.cnblogs.com/xuxiaobo/p/19012579

浙公网安备 33010602011771号