鉴权方式
HyperZoneFRP Panel 面向开发者的接口统一使用 JWT 强制鉴权;登录、注册等公开接口无需令牌,已开启两步验证的账户走两段式登录。每个接口在 接口参考 各章均有「鉴权」标注,本章说明校验链的精确行为、错误响应与常见坑。
JWT 强制鉴权
绝大多数用户端接口(/api/users/*、/api/nodes/*、/api/proxies/*、/api/auth/me 等)要求请求携带有效的 JWT,且通过会话双重校验:
Authorization: Bearer <token>校验链(逐条失败即中止)
- 提取令牌:只认
Authorization: Bearer请求头。JWT 禁止通过 URL Query 传递(避免凭据落入访问日志、代理日志与监控链路),传了也不会被识别。 - JWT 校验:签名与有效期验证,失败返回 401「无效的令牌或令牌已过期」。
- 会话校验:令牌必须在 Redis 中存在有效会话,失败返回 401「会话无效或已过期,请重新登录」。仅持有未过期 JWT 但会话已被清除(如重新登录、修改密码、管理员踢下线)的请求会被拒绝。
- 用户状态校验:
- 账户被封禁 → 403,响应体
data携带{ "isBanned": true, "ban_reason": "..." }; - 账户状态非
active或AuthVersion不匹配(修改密码会递增该版本)→ 401「账户状态或认证版本已变更,请重新登录」。
- 账户被封禁 → 403,响应体
失败响应形态
json
{
"code": 401,
"message": "未提供认证令牌"
}| HTTP 状态 | 场景 |
|---|---|
| 401 | 未携带 Authorization 头 / JWT 无效或过期 / 会话无效或过期 / 用户不存在 / AuthVersion 变更 |
| 403 | 账户被封禁(data.isBanned=true,含 ban_reason) |
会话相关接口
GET /api/auth/me— 校验通过后可拿到当前用户完整资料;GET /api/auth/sessions— 列出本人全部会话(含 IP、浏览器、是否当前会话);DELETE /api/auth/sessions/:sessionId— 吊销单个会话;POST /api/auth/sessions/heartbeat— 会话保活;POST /api/auth/logout— 删除当前会话。该接口故意公开:JWT 已过期也能登出,清理本地凭据即可,不必先刷新令牌。
访问密钥签到鉴权(仅 POST /api/users/checkin)
签到是全站唯一支持访问密钥替代 JWT 的接口,供脚本/定时任务免登录自动签到:
X-Access-Key: <访问密钥>bash
curl -X POST -H 'X-Access-Key: <访问密钥>' \
'https://api.hyperfrp.com/api/users/checkin'- 访问密钥即「安全设置 → 密码与访问密钥」中展示的 32 位小写 hex 字符串,与 frpc 配置内嵌的凭证同源(
users.access_key); - 凭证只允许走请求头,不接受 URL Query / 请求体传递;
- 请求同时携带
Authorization: Bearer时一律按 JWT 校验,校验失败不回退访问密钥——避免会话过期被静默换道掩盖; - 无效或格式非法的密钥统一 401「访问密钥无效」;封禁账户 403(
data.isBanned=true,与 JWT 封禁同构);非active账户 401「账户状态异常,无法使用访问密钥」; - 重置访问密钥后旧密钥立即失效:签到脚本与 frpc 配置同时失效,需同步更新;
- 该替代通道仅对签到开放——
/api/users/*其余接口(改密码、关 2FA 等)只认 JWT,访问密钥不会因此获得会话权限。接口细节见用户章节 · 签到。
两步验证(2FA)登录流
开启两步验证的用户,登录接口不会直接返回正式令牌,而是走两段式:
POST /api/auth/login
│ 命中 2FA
▼
{ "requires2FA": true, "tempToken": "..." } ← 无 JWT
│
▼
POST /api/auth/2fa/verify { "tempToken": "...", "code": "123456" }
│
▼
{ "token": "...", "expiresIn": ..., "user": {...} } ← 正式 JWTtempToken短时效、单用途,仅用于换取正式令牌;- 未开启 2FA 的用户登录一次即返回
token,不存在requires2FA字段(见 认证与会话)。
实践建议
- 令牌存储与续期:登录响应含
token与expiresIn(秒)。长期在线的客户端应定期调用POST /api/auth/sessions/heartbeat维持会话;会话失效后所有Protect接口统一返回 401,应引导重新登录而非重试。 - 封禁处理:收到 403 且
data.isBanned=true时停止重试,向用户展示ban_reason。 - 排查请求:每个响应都带
X-Request-ID头(客户端可自带合法值对齐调用链,非法值会被服务端静默替换),报障时提供该 ID 可在服务端结构化日志中精确定位。