API 令牌怎么发、怎么存、怎么验?签名令牌安全吗?怎么吊销?放在 URL 里行不行?这篇把每个问题都用实际请求验证一遍,包括真实 gunicorn 访问日志的检查。
没有 Authorization 头 → 401 {"error":"unauthorized","reason":"missing"} | WWW-Authenticate: Bearer realm="api"
Authorization: Token abc(不是 Bearer) → 401 {"error":"unauthorized","reason":"malformed"} | WWW-Authenticate: Bearer realm="api"
Authorization: Bearer(没有令牌) → 401 {"error":"unauthorized","reason":"malformed"} | WWW-Authenticate: Bearer realm="api"
Authorization: Bearer 错误令牌 → 401 {"error":"invalid token"} | WWW-Authenticate: Bearer error="invalid_token"
Authorization: bearer 正确令牌(小写) → 200 {"uid":1} | WWW-Authenticate: None
Authorization: Bearer 正确令牌 → 200 {"uid":1} | WWW-Authenticate: None
401 与 403:普通用户访问 /admin → 403 | 管理员 → 200上一篇:Idempotency-Key;下一篇:JWT 登录认证。
令牌 qU6G0vk4TljGScGmXZWbKxq_LZMolXY5LwXX2GgL-fE (长度 43,secrets.token_urlsafe(32) = 32 字节随机数 → 43 个字符)
服务端存的是 sha256 十六进制: 585ce88ff6eb6e19e442702a… (长度 64)——数据库泄漏时拿不到可用令牌
对比 hmac.compare_digest("a", "a") = True (比较哈希时用它,不用 ==) 令牌: eyJ1aWQiOjF9.ar87ow.HaKy25Hyhou809lkrNYY6CGlgkg
不需要密钥就能解出 payload: {"uid":1}
验证通过 → 200 {'uid': 1}
篡改签名 → 401 {'error': 'invalid token'}
改 payload 里的 uid 为 2(沿用原签名)→ 401
max_age=1 秒,等 2 秒后 → 401 {'error': 'token expired'}不透明令牌删除后 → 401 签名令牌:吊销动作之后(这里没有存储可删)→ 200 (仍然 200,要吊销必须另存黑名单或检查用户状态) 用户被删除后签名令牌 → 401 (因为视图里还检查了用户是否存在)
日志里能搜到查询参数里的令牌: True | 能搜到头里的令牌: False 访问日志行示例: 127.0.0.1 - - [02/Oct/2026:13:05:42 +0800] "GET /me?token=SECRET-IN-QUERY HTTP/1.1" 200 2 "-" "-"