DEVELOPERS

在 disk.zone 之上构建

disk.zone 的账号、余额和登录状态可以被其他项目复用:*.disk.zone 下的子项目静默共享登录,第三方网站用 OAuth 2.0 / OpenID Connect 接入,每个公开操作都是一个 HTTP 接口。无论哪种方式,拿到的都是同一个永久用户 ID,也就是用户名。

同域项目静默登录

所有 *.disk.zone 子项目与 disk.zone 共享登录和退出状态:在任意一处登录,处处已登录;在任意一处退出,处处退出。登录状态保存在 disk.zone 域的共享会话 Cookie 里(HttpOnly,页面脚本读不到),子项目的后端通过 Platform 服务绑定验证每一个请求。

前端:sso.js

在页面里引入 SDK,就能读取当前用户、监听登录状态、打开登录窗口或退出。登录窗口像 Google 登录那样以 iframe 浮层打开,用户不用离开当前页面。

<script src="https://disk.zone/sdk/sso.js"></script>
<script>
  // 当前用户:{ id, username, status },未登录时为 null
  DiskZone.me().then((user) => render(user));

  // 任何一处登录或退出都会通知(订阅后先回调一次当前状态)
  const stop = DiskZone.onChange((user) => render(user));

  // 打开登录窗口(iframe 浮层);成功后得到用户
  loginButton.onclick = () => DiskZone.login().then(render);
  logoutButton.onclick = () => DiskZone.logout();
</script>
  • DiskZone.me():当前用户 { id, username, status };未登录时为 null。返回 Promise。
  • DiskZone.onChange(cb):登录状态变化时回调,订阅后先回调一次当前状态;返回取消订阅的函数。
  • DiskZone.login():打开登录窗口(iframe 浮层),成功后得到用户;login({ mode: "register" }) 直接打开注册。
  • DiskZone.logout():退出 disk.zone,所有 *.disk.zone 项目同时退出。返回 Promise。

后端:Platform 服务绑定

在子项目的 wrangler 配置里绑定 Platform 服务,把请求的 Cookie 与 Authorization 头交给它验证。SDK 只负责界面,后端必须自己验证每一个请求;会话一旦退出或被撤销,下一个请求就会验证失败。

// wrangler.jsonc
"services": [{ "binding": "PLATFORM", "service": "main", "entrypoint": "Platform", "props": { "project": "<项目名>" } }]

// 每个请求
const auth = await env.PLATFORM.authenticate({
  cookie: request.headers.get('cookie') ?? undefined,
  authorization: request.headers.get('authorization') ?? undefined,
});
if (!auth.ok) return new Response('请先登录', { status: 401 });
auth.user.id; // 永久用户 ID(用户名)

同一个绑定还能读取用户资料,并从用户余额按量扣费或退款;每一笔都记在用户同一份余额的账单里。

第三方 OAuth 2.0 / OpenID Connect

不在 *.disk.zone 下的网站,用标准的 OAuth 2.0 授权码流程接入,必须使用 PKCE(S256),兼容 OpenID Connect。用户在 disk.zone 上确认授权后,你的网站拿到的 sub 就是用户的永久 ID(用户名)。

# 1. 把用户带到授权页(code_challenge = BASE64URL(SHA256(code_verifier)))
https://disk.zone/oauth/authorize?response_type=code&client_id=<client_id>
  &redirect_uri=https://example.com/callback&scope=openid%20profile
  &state=<随机串>&code_challenge=<challenge>&code_challenge_method=S256

# 2. 用回调拿到的 code 换取令牌(机密客户端另带 client_secret,或用 HTTP Basic 认证)
curl -X POST https://disk.zone/oauth/token \
  -d grant_type=authorization_code -d code=<code> \
  -d redirect_uri=https://example.com/callback \
  -d client_id=<client_id> -d code_verifier=<verifier>

# 3. 读取用户信息
curl https://disk.zone/oauth/userinfo -H "Authorization: Bearer <access_token>"
→ {"sub":"alice","preferred_username":"alice","name":"alice",…}

访问令牌和 ID 令牌是 ES256 签名的 JWT,有效 1 小时,可以用 JWKS 公钥自行验证;只有申请了 offline_access 时才签发 refresh_token,它每次使用都会轮换。

sso.js 也为第三方网站准备了两个小工具:DiskZone.pkce() 生成 code_verifier 与 code_challenge,DiskZone.authorizeUrl({ client_id, redirect_uri, state, code_challenge }) 拼出授权地址。

应用(client_id 与回调地址)由 disk.zone 团队登记。令牌和用户在 disk.zone 的登录会话绑定:用户退出后,令牌随之失效。

公开 API

disk.zone 的每个公开操作都是一个 HTTP 接口,网页本身也只是调用这些接口。接口会自我介绍:

  • /api:全部公开接口的目录:方法、路径、参数和是否需要登录。
  • /api/openapi.json:OpenAPI 3.1 描述,可以导入 API 客户端或代码生成器。
  • /llms.txt:写给 AI 的站点说明。

响应格式

{"ok":true,"data":…}
{"ok":false,"error":{"code":"snake_case","message":"中文说明"}}

error.code 是稳定的机器码,程序据此判断;message 是给人看的中文说明。时间均为 Unix 毫秒时间戳。

认证

  • 浏览器 Cookie:登录时传 mode=cookie:令牌写入 HttpOnly Cookie,同源请求自动携带、自动续期。
  • 访问令牌:登录时传 mode=token:返回 15 分钟有效的 access_token,以及每次续期都会轮换的 refresh_token。
  • API 密钥:在个人空间创建,格式 dzk.<用户名>.<keyid>.<secret>,只在创建时显示一次;适合脚本和 AI 智能体。
# 登录,拿到访问令牌
curl -X POST https://disk.zone/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"alice","password":"…","mode":"token"}'

# 带上访问令牌或 API 密钥调用
curl https://disk.zone/api/me -H "Authorization: Bearer <access_token 或 dzk.…>"
→ {"ok":true,"data":{"user":{"id":"alice",…}}}

首页 · KV 键值存储 · SQL 数据库 · FS 文件存储 · 开发者 · 个人空间

给 AI 工具:站点说明见 https://disk.zone/llms.txt,公开接口目录见 https://disk.zone/api,OpenAPI 描述见 https://disk.zone/api/openapi.json。