Python 解密JWT验证苹果登录

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Python 解密JWT验证苹果登录

Xjng   2020-03-11 我要评论
1. 验证苹果登录,官方提供两种验证方法,一种是token,另一个种是code。这里使用的是token 2. 登录流程: 3. 苹果客户端调用苹果API,获取到用户的信息,包括: 4. user_id 5. 昵称 6. identity_token 7. 苹果客户端发送identity_token到服务端 8. 服务端验证identity_token是否合法,并解析数据,得到user_id。这个user_id和上面的user_id是一样的 9. 服务端检查该user_id是否已注册,如果是,返回登录信息。如果否,注册。 10. 验证的原理: 11. 苹果会把用户的信息放在一个json里面,然后使用私钥对json签名。 12. 服务端调用苹果API拿到公钥,然后验证签名是否正确。 13. 所以总的来说就是使用RSA私钥签名的算法来保证数据不会被篡改。 12. identity_token解析后包含几部分内容 13. header。 13. 例子:`{u'alg': u'RS256', u'kid': u'86D88Kf'}` 14. alg是加密算法类型 14. kid是使用的公钥的id 15. payload或者claims 。也就是数据: 16. 例子: ``` { u'c_hash': u'HpjAKvLjivbJr9j9ZxfFxA', u'aud': u'com.kugou.moe', u'iss': u'https://appleid.apple.com', u'email_verified': u'true', u'nonce_supported': True, u'exp': 1583829815, u'auth_time': 1583829215, u'iat': 1583829215, u'email': u'huanghuixia5@163.com', u'sub': u'001712.90358ddaa2294989b3b7c88b30086b37.0724' # 用户唯一标志,相当于openid } ``` 17. aud 客户端的报名。 18. exp。超时时间,时间戳。当前时间如果大于这个时间,会报超时错误 19. email 用户的email 20. sub 用户的user_id ### demo 使用了python-jwt这个库。安装方法:`pip install python-jwt` ``` # encoding=utf8 import requests import logging import python_jwt as jwt, jwcrypto.jwk as jwk log = logging.getLogger('test') class AppleLoginManager(object): """ 苹果登录 """ @classmethod def get_key(cls, kid): """ 访问apple 获取公钥。apple的接口会返回很多公钥的,根据jwt数据header的kid,找到对应的公钥 :param kid: :return: { "kty": "RSA", "kid": "eXaunmL", "use": "sig", "alg": "RS256", "n": "4dGQ7bQK8LgILOdLsYzfZjkEAoQeVC_aqyc8GC6RX7dq_KvRAQAWPvkam8VQv4GK5T4ogklEKEvj5ISBamdDNq1n52TpxQwI2EqxSk7I9fKPKhRt4F8-2yETlYvye-2s6NeWJim0KBtOVrk0gWvEDgd6WOqJl_yt5WBISvILNyVg1qAAM8JeX6dRPosahRVDjA52G2X-Tip84wqwyRpUlq2ybzcLh3zyhCitBOebiRWDQfG26EH9lTlJhll-p_Dg8vAXxJLIJ4SNLcqgFeZe4OfHLgdzMvxXZJnPp_VgmkcpUdRotazKZumj6dBPcXI_XID4Z4Z3OM1KrZPJNdUhxw", "e": "AQAB" } """ ret = requests.get('https://appleid.apple.com/auth/keys') ret_json = ret.json() for key in ret_json['keys']: if key['kid'] == kid: return key log.error(u'[苹果登录]找不到对应的kid %s %s' % (kid, ret_json)) raise Exception('找不到对应的kid') @classmethod def verify_jwt(cls, token): """ 验证jwt数据,返回: { u'c_hash': u'HpjAKvivbJr9j9ZxfFxA', u'aud': u'com.test.moe', u'iss': u'https://appleid.apple.com', u'email_verified': u'true', u'nonce_supported': True, u'exp': 1583829815, u'auth_time': 1583829215, u'iat': 1583829215, u'email': u'hua@163.com', u'sub': u'0017xx.9035989b3bxxxxx7c88b30086b37.xxx' # 用户唯一标志,相当于openid } """ header, claims = jwt.process_jwt(token) # 获取信息,但是不验证 if claims['aud'] != 'com.test.test': # 检验是不是自己的安装包名 log.error(u'[苹果登录]aud异常 aud:%s token:%s' % (claims['aud'], token)) raise Exception(u'安装包名异常') key_obj = AppleLoginManager.get_key(header['kid']) key = jwk.JWK(**key_obj) header, claims = jwt.verify_jwt(token, key, [key_obj['alg']], checks_optional=1) # 获取信息并验证 return claims @classmethod def get_access_info(cls, token): """获取授权信息""" try: resp_json = AppleLoginManager.verify_jwt(token) return { "open_id": resp_json['sub'], } except: log.exception(u'苹果登录异常,token:%s' % token) raise Exception('苹果登录异常') token = '''xxxx''' #前端传过来的 identity_token AppleLoginManager.get_access_info(token) ```

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们