前言
Easycrawl 的预览和下载功能将基于 Dropbox 实现,免人工维护、可以长久使用的 Token 是绝对必要的。
但是由于自 Dropbox 使用 OAuth 2.0 进行授权后就停止生成长寿命的 access_token:Migrating App Permissions and Access Tokens,因此只能使用过期前刷新令牌的方式来实现永久访问了。
方案概述
OAuth 2.0授权模式下的基础概念- 新建 Dropbox App 并获取各值
- 刷新令牌实现流程的可视化
- 使用 Python3 实现令牌的自动刷新
详细内容
一、OAuth 2.0 授权模式下的基础概念
1、(short-lived) access token
短期访问令牌,所有的 Dropbox API 请求都需要携带 access_token 作为身份验证。
默认生成的 access_token 有效期为 4 小时,过期后需要重新获取。
2、refresh token
刷新令牌,可以用来获取新的 access_token。
refresh_token 永不过期,可以一直使用,除非用户撤销应用的访问权限。
refresh_token 只能通过 OAuth 2.0 授权流程获取一次,之后需要妥善保存。
3、app key 和 app secret
app_key 和 app_secret 是应用的唯一标识和密钥,用于身份验证。
app_key 是公开的,可以在客户端代码中使用。
app_secret 是私密的,必须保存在服务器端,不能暴露给客户端。
4、OAuth 2.0 授权流程
- 用户访问应用,应用引导用户到 Dropbox 的授权页面,用户登录并授权应用访问其 Dropbox 账户。授权成功后,Dropbox 重定向用户回应用,并附带一个授权码(后续代码中标识为
access_code)。 - 应用使用授权码向 Dropbox 请求
access_token和refresh_token。 - 应用使用
access_token访问 Dropbox API。 - 当
access_token过期后,应用使用refresh_token请求新的access_token。
二、新建 Dropbox App 并获取各值
前往 App 控制台:App Console - Dropbox


之后就获取到了值:
app_key: 1jhdvh6zytcXXXXapp_secret: g7nox5hlfb6XXXX
OAuth 2 认证后的重定向链接不用管,不是必要的。
三、刷新令牌实现流程的可视化

四、使用 Python3 实现令牌的自动刷新
import requests
APP_KEY = "1jhdvh6zytcxxxx"
APP_SECRET = "g7nox5hlfb6xxxx"
def _first_get_access_code():
url = "https://www.dropbox.com/oauth2/authorize" \
+ "?client_id={}".format(APP_KEY) \
+ "&token_access_type=offline" \
+ "&response_type=code"
access_code = input("Go to the following URL and authorize the app:\n{}\nThen enter the code here: ".format(url))
return access_code
def _second_get_refresh_token(access_code):
url = "https://api.dropboxapi.com/oauth2/token"
data = {
"code": access_code,
"grant_type": "authorization_code",
"client_id": APP_KEY,
"client_secret": APP_SECRET,
}
response = requests.post(url, data=data)
print("> Response Status Code:", response.status_code)
print("> Response Text:", response.text) # > Response Text: {"access_token": "sl.xxx", "refresh_token": "xxxx"...
refresh_token = response.json().get("refresh_token")
return refresh_token
def _third_refresh_access_token(refresh_token):
url = "https://api.dropboxapi.com/oauth2/token"
data = {
"refresh_token": refresh_token,
"grant_type": "refresh_token",
"client_id": APP_KEY,
"client_secret": APP_SECRET,
}
response = requests.post(url, data=data)
print("> Response Status Code:", response.status_code)
print("> Response Text:", response.text) # > Response Text: {"access_token": "sl.xxx", "token_type": "bearer"...
access_token = response.json().get("access_token")
return access_token
def _fourth_use_access_token(access_token):
url = "https://api.dropboxapi.com/2/users/get_current_account"
headers = {
"Authorization": "Bearer {}".format(access_token)
}
response = requests.post(url, headers=headers)
print("> Response Status Code:", response.status_code)
print("> Response Text:", response.text) # > Response Text: {"account_id": "dbid:xxxx", "name": {"given_name": "xxx"...
def main():
"""
主方法
"""
# 1. 获取 access code
access_code = _first_get_access_code()
print("Access Code:", access_code) # Access Code: gUeuzCLrRU0AAAAAAAAAGr8nqqMK3qcwhu4ZbaEXXXX
# 注意 access_code 只能使用一次
# 因此每次获取之后的 refresh_token 都需要重新获取 access_code
# 2. 用 access code 换取 refresh token
refresh_token = _second_get_refresh_token(access_code)
print("Refresh Token:", refresh_token) # Refresh Token: P7vSxBhf2FEAAAAAAAAAAQ_vXY2SQecMN_sCvhZuDea2N-1VofCZzSVgSSPwXXXX
# 3. 保存 refresh token 到安全的地方,后续可以用它来获取新的 access token
with open("dropbox_refresh_token.txt", "w") as f:
f.write(refresh_token)
access_token = _third_refresh_access_token(refresh_token)
print("Access Token:", access_token) # Access Token: sl.AF_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 4. 使用 access token 访问 Dropbox API
_fourth_use_access_token(access_token)
# 之后超过 4 小时后,再次实行第二部的刷新令牌
if __name__ == "__main__":
main()