• 工具-百度云盘服务-身份认证


    目标

    通过百度网盘API的方式去获取网盘中的文件,要实现这的第一步就是需要获取网盘的权限。
    
    • 1

    资料(参考)

    如果期望应用访问用户的网盘文件,则需要经过用户同意,这个流程被称为“授权”。百度网盘开放平台基于 OAuth2.0 接入授权。OAuth2.0 是一种授权协议,通过该协议用户可以授权开发者应用访问个人网盘信息与文件。
    用户同意授权后,开发者应用会获取到一个 Access Token,该 Access Token 是用户同意授权的凭证。开发者应用需要依赖 Access Token 凭证调用百度网盘公开API,实现访问用户网盘信息与授权资源。
    关于实现用户授权,您可以选择授权码模式、简化模式或者设备码模式实现。
    当前百度网盘开放平台支持三种授权模式:授权码模式(Authorization Code)、简化模式(Implicit Grant)、设备码模式(Device Code)。您可以根据自身业务,选择合适的授权模式,实现用户授权。
    
    • 1
    • 2
    • 3
    • 4
    授权模式描述使用场景有效期
    授权码模式(Authorization Code)用户授权后生成授权码 Code,开发者应用通过 Code 换取 Access Token。适用于 有 Server 端 的应用。Access Token 有效期30天,过期后支持刷新。
    简化模式(Implicit Grant)无需通过 Code 换取 Access Token,直接获取 Access Token。适用于 无 Server 端配合 的应用。Access Token 有效期30天,过期后不支持刷新, 用户需重新登录授权。
    设备码模式(Device Code)获取设备码,用户授权后,开发者应用通过设备码换取 Access Token。适用于 弱输入设备 的应用(不支持浏览器或输入受限的设备,如儿童手表)。Device Code只能使用一次,Access Token过期后支持刷新。
    授权注意事项:
    • Access Token 有效期30天,过期后支持刷新,刷新后的 Access Token 有效期仍为 30 天。
    • 刷新Access Token请按需刷新,不需要不停的刷新。
    • 刷新请求,如果API返回失败,旧的refresh_token会失效,此时需要重新发起授权请求,获取新的 Access Token、refresh_token,而不是使用旧的 refresh_token 循环再发起刷新请求。
    • refresh_token 只支持使用一次,refresh_token 使用后失效,下次刷新 Access Token 时需要使用上一次刷新请求响应中的 refresh_token。

    准备

    在授权之前,您需要先完成创建自己的应用。
    主要包括以下流程:

    1. 进入百度网盘开放平台,点击右上角 “申请接入”。
    2. 登录您的百度帐号。
    3. 完成开发者认证,我们提供了两种认证类型供您选择:个人认证、企业认证。
    4. 前往控制台创建自己的应用,生成AppID、AppKey、SecretKey、SignKey等信息。
      目前个人认证下可最多创建 2 个应用,企业认证下可最多创建 10 个应用。
      可创建两种类型的应用:硬件应用和软件应用。
    5. 至此,完成应用的创建。

    实现逻辑

    授权码模式适用于有 Server 端的应用。我们这次实现是选用的授权码模式。
    开发者应用在获取用户的授权码 Code 之后,通过 Code 换取 Access Token 凭证
    Access Token 有效期30天,过期后支持刷新,刷新后的 Access Token 有效期仍为 30 天,刷新Access Token请按需刷新,不需要不停的刷新。
    刷新请求,如果API返回失败,旧的refresh_token会失效,此时需要重新发起授权请求,获取新的 Access Token、refresh_token,而不是使用旧的 refresh_token 循环再发起刷新请求。
    refresh_token 只支持使用一次,refresh_token 使用后失效,下次刷新 Access Token 时需要使用上一次刷新请求响应中的refresh_token。
    获取到的授权码 code 有效期 10 分钟,且仅一次有效。
    简单介绍时序图的流程,如下:

    1. 用户选择通过百度账号登录开发者应用。
    2. 开发者应用发起授权码 Code 请求。
    3. 百度 OAuth 服务器展示授权页面给用户,用户登录并同意授权。
    4. 用户同意授权后,百度 OAuth 服务器会将页面跳转至开发者应用配置的回调地址,返回授权码 Code。
    5. 开发者应用发起 Code 换取 Access Token 请求。
    6. 百度 OAuth 服务器返回 Access Token 凭证。
      授权码模式

    实现步骤:

    1. 获取授权码,需要页面登录认证,且需要传入参数(授权码只可用一次)
      登录链接格式: https://openapi.baidu.com/oauth/2.0/authorize?client_id=app_key&device_id=app_id&errmsg=Auth+Login+Ptoken+Error&errno=10&redirect_uri=oob&response_type=code&scope=basic%2Cnetdisk&ssnerror=1
      需要传入参数(后面几个参数可以固定)为: device_id client_id redirect_uri=oob response_type=code scope=basic,netdisk
    	# 1. 获取授权码 需页面登录认证
        def get_authorization_code(self):
            import requests
            url = 'http://openapi.baidu.com/oauth/2.0/authorize'
            payload = {
                'response_type':'code',
                'device_id': self.device_id,
                'client_id': self.client_id,
                'scope': 'basic, netdisk',
                'redirect_uri': 'oob'
            }
            headers = {
                'User-Agent': 'pan.baidu.com'
            }
            print(url)
            response = requests.request("GET", url, headers=headers, data=payload)
            print(response.text)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1. 使用授权码换取AccessToken凭证
      上面资料中提到token的有效期是30天,该请求会返回一个refresh_token值,由于后续刷新需要上一次的值,所以后续我们需要考虑把这个值保存到本地。
    	# 2. 换取AccessToken凭证 将token信息保存到本地,支持后续读取更新
        def oauthtoken_authorizationcode(self, file_path = 'tokens.json'):
            with openapi_client.ApiClient() as api_client:
                api_instance = auth_api.AuthApi(api_client)
                code = self.code
                client_id = self.client_id
                client_secret = self.client_secret
                redirect_uri = self.redirect_uri
                try:
                    api_response = api_instance.oauth_token_code2token(code, client_id, client_secret, redirect_uri)
                    access_token = self.save_tokens_info(api_response, file_path)
                    return access_token, file_path
                except openapi_client.ApiException as e:
                    print("使用code换取AccessToken凭证失败: %s\n" % e)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 刷新AccessToken
      由于获取授权码需要页面验证,开发使用时很不方便,所以需要把token信息保存到本地,用了支撑刷新及更新token
      实现
    	# 3. 刷新 Access Token 将token信息保存到本地
        def oauthtoken_refreshtoken(self, file_path = 'tokens.json'):
            with open(file_path, 'r') as f:
                data = json.load(f)
            print(data)
            if (datetime.datetime.strptime(data['expires_time'], "%Y-%m-%d %H:%M:%S") > datetime.datetime.now()):
                print('access_token:',data['access_token'],',未过期,过期时间:',data['expires_time'])
                return data['access_token']
            else:
                with openapi_client.ApiClient() as api_client:
                    api_instance = auth_api.AuthApi(api_client)
                    refresh_token = data['refresh_token']
                    client_id = self.client_id
                    client_secret = self.client_secret
                    try:
                        api_response = api_instance.oauth_token_refresh_token(refresh_token, client_id, client_secret)
                        access_token = self.save_tokens_info(api_response, file_path)
                        return access_token
                    except openapi_client.ApiException as e:
                        print("刷新Access Token失败: %s\n" % e)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    工具函数: 保存到本地

    # 将token信息保存下来
        def save_tokens_info(self, api_response, file_path):
            tokens_dict = {'access_token': api_response.access_token,
                           'expires_in': api_response.expires_in,
                           'expires_time': (datetime.datetime.now() + datetime.timedelta(
                               seconds=api_response.expires_in)).strftime("%Y-%m-%d %H:%M:%S"),
                           'refresh_token': api_response.refresh_token,
                           'scope': api_response.scope,
                           'session_key': api_response.session_key,
                           'session_secret': api_response.session_secret}
            print('tokens信息为:', tokens_dict)
            # 将数据写入json文件
            with open(file_path, 'w') as f:
                json.dump(tokens_dict, f)
            print('tokens结果保存到本地:', file_path)
            return api_response.access_token
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    最终运行

    if __name__ == '__main__':
        client = Baidu()
    	client.oauthtoken_authorizationcode()
        client.oauthtoken_refreshtoken()
    
    • 1
    • 2
    • 3
    • 4

    总结

    在调试过程时,一次性code和一次性refresh使用时很不便利,这两个变量不是时效性的,是需要注意的。

  • 相关阅读:
    顾客点餐系统-----操作菜品JDBC代码的编写(1)
    【Unity】VS Code 没有自动补全 MonoBehaviour 的方法
    程序员为什么要学习数据结构与算法?
    Java计算机毕业设计德云社票务系统源码+系统+数据库+lw文档
    71.【Java.哈希表(散列表)】
    锚点优化步步为赢:详细解析关键知识点和最佳实践,提升网页的关联性与权威性!
    【后端速成 Vue】初识指令(上)
    大厂招聘IO常问面试题
    Python函数式编程(一)概念和itertools
    webpack5 使用cache对Eslint和Babel缓存提升打包构建速度
  • 原文地址:https://blog.csdn.net/qq_28844767/article/details/136658690