第36章 Cloudreve 身份认证指南:JWT 验证与 OAuth 2.0 集成
认证方式 查看具体 API 文档时,每个接口的认证类型都会有标注。
认证类型如下:
Auth: None 无需认证
无需发送 Authorization 请求头。
Auth: JWT Required 需要认证
必须提供 Authorization 请求头,格式为 Bearer
Auth: JWT Optional 可选认证
可以不发送 Authorization 请求头。如果发送了,请求将以已认证用户的身份执行;如果未发送,则以匿名用户身份执行。
通过 OAuth 获取 AccessToken(推荐) Cloudreve 支持标准的 OAuth 2.0 授权码流程,允许第三方应用安全地获取用户授权。对于需要代表用户访问 Cloudreve 的应用,这是推荐的方式。
注册 OAuth 应用 使用 OAuth 之前,需要先在 Cloudreve 管理面板中注册你的应用:
以管理员身份登录,进入 Dashboard -> OAuth Apps 点击 New OAuth App 填写必要信息: App Name:授权时展示给用户的应用名称 App Icon:图标 URL 或 Iconify 图标名(如 mdi:application) Client Secret:生成或填写一个密钥(请妥善保管) Redirect URIs:一个或多个用于接收授权码的回调地址(每行一个) Permissions (Scopes):选择你的应用所需的权限 保存应用,并记录下 Client ID 和 Client Secret 授权流程 1. 将用户重定向到授权页面 将用户重定向到授权端点,并携带以下参数:
GET /session/authorize
参数 是否必填 说明 response_type 是 必须为 code client_id 是 你的应用的 Client ID redirect_uri 是 已注册的回调地址之一 scope 是 以空格分隔的权限列表 state 否 自定义状态字符串,将原样传给回调地址 code_challenge 否 PKCE code challenge(推荐) code_challenge_method 否 如果提供了 code_challenge,必须为 S256
授权 URL 示例:
https://your-cloudreve-site.com/session/authorize? response_type=code& client_id=393a1839-f52e-498e-9972-e77cc2241eee& redirect_uri=https://your-app.com/callback& scope=openid%20profile%20offline_access%20Files.Write& state=random_state_string& code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM& code_challenge_method=S256
2. 用户授权应用 用户将被要求登录(如未登录)并授权所请求的权限。授权通过后,Cloudreve 会将用户重定向回你的 redirect_uri:
https://your-app.com/callback?code=AUTHORIZATION_CODE&state=
3. 用授权码换取令牌 向令牌端点发送 POST 请求,用授权码换取 access token 和 refresh token。
请参考 Exchange token API 文档。
httpPOST /api/v4/session/oauth/token Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code& client_id=YOUR_CLIENT_ID& client_secret=YOUR_CLIENT_SECRET& code=AUTHORIZATION_CODE& code_verifier=YOUR_CODE_VERIFIER
参数 是否必填 说明 grant_type 是 必须为 authorization_code client_id 是 你的应用的 Client ID client_secret 是 你的应用的 Client Secret code 是 回调中收到的授权码 code_verifier否 如果使用了 code_challenge 则必填
响应:
json{ "access_token": "eyJhbGciOiJIUzI1NiIs...", "refresh_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "Bearer", "expires_in": 3600, "refresh_token_expires_in": 7776000 }
PKCE(Proof Key for Code Exchange) 推荐所有 OAuth 客户端都使用 PKCE,尤其是无法安全保存 client secret 的公共客户端(移动应用、SPA)。即使是机密客户端,PKCE 也能提供额外的安全保障。
生成 PKCE 参数 生成一个随机的 code_verifier(43-128 个字符,取值范围为 A-Z、a-z、0-9、-、.、_、~) 对 code_verifier 计算 SHA-256 哈希,再进行 base64url 编码,得到 code_challenge 示例(JavaScript):
javascript// 生成随机 code verifier function generateCodeVerifier(length = 64) { const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"; const randomValues = new Uint8Array(length); crypto.getRandomValues(randomValues); return Array.from(randomValues, (v) => charset[v % charset.length]).join(""); }
// 由 code verifier 生成 code challenge async function generateCodeChallenge(codeVerifier) { const encoder = new TextEncoder(); const data = encoder.encode(codeVerifier); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = new Uint8Array(hashBuffer);
// Base64url 编码 let base64 = ""; for (let i = 0; i < hashArray.length; i++) { base64 += String.fromCharCode(hashArray[i]); } return btoa(base64) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=+$/, ""); }
// 用法 const codeVerifier = generateCodeVerifier(); const codeChallenge = await generateCodeChallenge(codeVerifier);
// 将 codeVerifier 安全保存,供令牌交换时使用
刷新 AccessToken 警告 要获得 refresh_token,授权请求中必须包含 offline_access 权限。否则只会返回 access_token。
AccessToken 过期后,可以使用 RefreshToken 获取新的一对令牌。请参考 Refresh token 方法。
httpPOST /api/v4/session/token/refresh Content-Type: application/json
{ "refresh_token": "YOUR_REFRESH_TOKEN" }
响应:
json{ "code": 0, "data": { "access_token": "eyJhbGciOiJIUzI1NiIs...", "refresh_token": "eyJhbGciOiJIUzI1NiIs...", "access_expires": "2025-04-26T16:19:38.833494+08:00", "refresh_expires": "2025-10-23T15:19:38.833495+08:00" }, "msg": "" }
当 RefreshToken 过期或刷新请求失败时,客户端应引导用户重新授权应用。
OAuth 端点参考 端点 URL Authorization https://your-site.com/session/authorize Token https://your-site.com/api/v4/session/oauth/token Refresh Token https://your-site.com/api/v4/session/token/refresh User Info https://your-site.com/api/v4/session/oauth/userinfo
通过登录获取 AccessToken 登录 通过密码登录或其他登录接口成功登录后,你将获得一对 AccessToken 和 RefreshToken,以及它们的过期时间:
json{ "code": 0, "data": { "user": ..., "token": { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwic3ViIjoibHB1YSIsImV4cCI6MTc0NTY1NTU3OCwibmJmIjoxNzQ1NjUxOTc4fQ.L1ETHHBNImNevze00QAgrrY1maZO2nefyIwdT4cb68c", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsInN1YiI6ImxwdWEiLCJleHAiOjE3NjEyMDM5NzgsIm5iZiI6MTc0NTY1MTk3OCwic3RhdGVfaGFzaCI6Ikk1OCtSbmsrTHVpTkxBbjBqek9KNG45OUorV3hqL0pzbjJoRVYrUXBhelE9In0.Q2s75zxPVA3bzZyIIBau3TBvqSxIdzbiEmK1zCd-_zk", "access_expires": "2025-04-26T16:19:38.833494+08:00", "refresh_expires": "2025-10-23T15:19:38.833495+08:00" } }, "msg": "" }
客户端应将 AccessToken 和 RefreshToken 安全地保存在本地。请求需要认证的 API 时,在请求头中携带 AccessToken:
httpPOST /api/v4/xxx
Authorization: Bearer
刷新 AccessToken AccessToken 过期后,客户端应使用 RefreshToken 获取新的一对 AccessToken 和 RefreshToken。请参考 Refresh token 方法。
当 RefreshToken 过期或 Refresh token 请求失败时,客户端应引导用户重新登录。
直接生成 AccessToken(仅限本地调试) 本地调试时,如果不想通过登录获取 AccessToken,可以使用站点的 master key 直接生成一个。
获取站点 Master Key 警告 master key 对站点安全至关重要,切勿泄露给他人,也不要在生产环境中使用这种认证方式。
master key 在 Cloudreve 初始化时生成,保存在数据库的 settings 表中。你可以使用数据库管理工具或以下 SQL 语句获取:
sqlSELECT `value` FROM `settings` WHERE `name` = 'secret_key';
生成 AccessToken 使用 HS256 算法和站点 master key,为以下 payload 生成 JWT 令牌,作为 AccessToken 使用:
json{
"token_type": "access",
"sub": "
其中