星线账户接口接入
账户网页接口使用同站 Cookie、精确来源和 CSRF 校验。它们适用于账户前端;第三方业务登录应使用开放平台的 OIDC,不要求用户向第三方提交账户密码。资料依据 2026 年 10 月 23 日 identity/server/ 源码整理,介绍请求顺序、字段与失败边界。
建立请求上下文
首先调用 GET /api/csrf,保留服务端下发的 CSRF Cookie,并读取返回的 csrfToken。后续浏览器写请求同时携带 Cookie、正确 Origin 和 x-csrf-token。CSRF Cookie 使用 Strict SameSite,期限 3,600 秒;刷新页面后可以重新取得值。请求被来源检查拒绝时,反复更换验证码不会解决问题。
// 在账户站同源页面执行;captchaProof 来自当前 CAPTCHA 验证。
const { csrfToken } = await fetch('/api/csrf', {
credentials: 'same-origin'
}).then(r => r.json());
const response = await fetch('/api/auth/email-code', {
method: 'POST', credentials: 'same-origin',
headers: { 'content-type': 'application/json', 'x-csrf-token': csrfToken },
body: JSON.stringify({ identifier: 'reader@example.invalid', captcha: captchaProof })
});
const result = await response.json();
示例邮箱是合成数据。CAPTCHA 结构以账户前端及 identity/server/captcha.ts 为准,不用占位字符串模拟通过。服务端校验 Host 是否属于配置来源;生产要求 HTTPS。普通写请求的正文必须是 JSON 对象。OIDC 协议和签名开放 API 有专门认证机制,小程序只有 inspect、decide 使用单次证明的例外,不应把这些例外扩散到其他路由。
注册顺序
| 方法与路径 | 主要输入 | 后续动作 |
|---|---|---|
POST /api/register/start |
email、captcha |
保存 transactionId,等待邮箱验证码 |
POST /api/register/email/send |
transactionId、captcha |
仅用于重发,不延长客户端自己计算的期限 |
POST /api/register/email/verify |
transactionId、code |
继续手机号和密码步骤 |
POST /api/register/phone/send |
transactionId、phone、captcha |
向事务中的手机号发码 |
POST /api/register/phone/verify |
transactionId、code |
验证当前注册事务 |
POST /api/register/password |
transactionId、password |
设置符合策略的密码 |
POST /api/register/complete |
transactionId |
以服务端返回确定注册完成 |
POST /api/register/phone/start |
phone、captcha |
开始独立手机号注册流程 |
邮箱注册需要完成邮箱、手机号、密码三项条件。独立手机号注册使用 phone/start 后的事务进行 phone/verify,再 complete;不要额外调用邮箱流程制造第二个账户。注册事务受浏览器上下文约束,不能从另一设备领取。流程未完成返回 REGISTRATION_INCOMPLETE,事务失效返回 INVALID_TRANSACTION;应按服务端状态回退或重新开始。
密码按 Unicode 码点计 12–128 个字符,同时 UTF-8 编码不超过 512 字节;服务端使用 Argon2id。邮箱会清理并转为小写,手机号按服务端支持范围规范化。客户端可以提前提示格式,但不能跳过服务端结果或把 HTTP 200 的发送受理视为联系方式验证。
登录、风险与会话
POST /api/auth/login 接受 method。密码方式提交 method:"password"、identifier、password;验证码方式提交 method:"email_code" 或 "phone_code",以及 identifier、transactionId、code。对应发送入口为 /api/auth/email-code、/api/auth/phone-code,均需要 CAPTCHA。手机发码还可带服务端给出的关联 transactionId。
服务端可能要求追加风险验证,继续调用 POST /api/auth/risk/send(transactionId、captcha)和 /api/auth/risk/verify(transactionId、code)。客户端应保留原事务,不在追加验证过程中重新创建并行登录。未知账户、冷却及部分不可投递状态使用统一发送响应,以减少账户枚举;实际投递基础设施完全不可用时仍可返回 503。
成功后使用 GET /api/auth/me 确认身份。返回包含 user、当前 session 的 id、method、createdAt、expiresAt,以及管理与认证能力标志。Cookie 由服务端设置,响应不会把原始会话令牌作为网页 JSON 字段公开。POST /api/auth/logout 退出当前 Account 会话;其他产品独立存储的会话需要各自处理。
会话响应中的时间是服务端记录,客户端应按到期时间显示状态,并在受保护操作返回未认证时重新验证。仅隐藏页面、删除某个前端变量或关闭浏览器标签不等于完成服务端会话撤销;网络异常时应保留明确的未确认结果。
安全设置、资料与授权
| 操作 | 路由与关键字段 | 约束 |
|---|---|---|
| 查看安全概况 | GET /api/security |
返回本人会话与安全事件等 |
| 重新验证 | POST /api/security/reauth |
根据 method 提交证明,可能继续短信验证;成功才取得 grantId |
| 改密码 | POST /api/security/password,grantId,password |
短时授权不可重复消费 |
| 联系方式变更 | POST /api/security/contact/send,grantId,kind,target,captcha;随后 /verify 提交 transactionId,code |
kind 仅邮箱或手机号 |
| 撤销会话 | POST /api/security/sessions/revoke,grantId,sessionId,或 grantId,target:"others" |
两个目标字段不能同时使用 |
| 资料更新 | POST /api/profile,displayName 及可选 avatar |
正文字节上限 400,000;不允许额外字段 |
| 资料头像 | GET /api/profile/avatar |
当前账户私有,禁止按他人 ID 构造公开地址 |
avatar 为 {mime,data},data 是标准 Base64;avatar:null 表示删除。更新资料时 displayName 应明确传递名称或 null,不能依靠省略字段模拟部分 PATCH。通行密钥的 options/verify 接口位于 identity/server/protocols.ts,使用 WebAuthn 原生响应与一次性挑战;不要自行拼装“认证成功”对象。实名认证申请的开关、材料和审核能力与普通资料更新独立。
错误、重试与观测
错误格式为 {error:{code,message},requestId}。日志可以记录 requestId、路由、时间和错误码,不能记录验证码、Cookie、密码、外部身份 code 或材料正文。
| 状态与代码 | 典型触发 | 处理方式 |
|---|---|---|
400 INVALID_INPUT / INVALID_CODE |
字段无效,验证码错误、过期或已使用 | 修正输入;不要无限重试同一码 |
400 INVALID_TRANSACTION |
事务到期、上下文或凭据改变、单次证明已用 | 重新开始相应验证 |
401 UNAUTHENTICATED / INVALID_CREDENTIALS |
会话或登录证明无效 | 清理页面认证状态,重新登录 |
403 CSRF_FAILED / FORBIDDEN |
Cookie 与头不匹配、来源或权限不符 | 先修复上下文或权限 |
403 RISK_BLOCKED / ACCOUNT_BANNED |
频率风险或账户限制 | 遵循提示,不切换标识规避 |
409 CONFLICT |
唯一数据冲突 | 刷新当前状态后处理 |
503 DELIVERY_UNAVAILABLE / SERVICE_UNAVAILABLE |
投递未配置或依赖异常 | 有界退避;明确保留“结果未确认” |
限额有全局、来源、目标与路由不同桶,默认窗口 600 秒、基础额度 20;不能把该值解释为全站所有用户合计每十分钟 20 次。发送冷却与接口限额同样存在。发生写请求超时时,先读取当前事务或安全设置核实,不自动重复提交注销、改密等一次性操作。
联调应分别覆盖完整注册、错误验证码与重放、风险追加验证、CSRF、跨浏览器事务、封禁、会话到期、改密后的授权变化、头像边界和投递失败。源码测试、构建成功只能验证其覆盖范围;生产配置、真实投递和第三方平台回调需要单独回执。服务组成与存储要求见技术概览。