exp = now + 15m;黑名单 revoke(sig)被偷的 access token 最多用到 exp(几分钟);发现异常时把 signature 写进黑名单,服务端验签后再查黑名单,命中即 401。即便不能像 session 那样瞬时全量失效,窗口也被压到很短。
数据与服务 · 账号与安全
token 是服务器签名的一段字符串(header.payload.signature),客户端用 Authorization: Bearer 携带它发请求,服务器只验签名和 exp 就信任 claims——不查会话库,所以快、能跨服务,代价是过期前很难单条作废。
无状态 token 不靠服务端记录,而靠一段服务器签名的字符串自证身份。先在这一台签发、请求、推进时间、刷新、篡改、撤销,亲眼看到签名和 exp 如何决定结果,再读后面的规则命名。
服务器用密钥对 header.payload 签名得到一段自洽的 token;客户端用Authorization: Bearer … 携带它发请求,服务器只验签名和 exp,不查会话库。
(空)尚未签发;带 Bearer 请求会返回 401。
(空)长效 · 单独存储 · 服务端可撤销撤销列表为空——这正说明无状态 token 默认没有「按一下就即时失效」的记录。
还没有发过带 Bearer 的请求;点「带 Bearer 请求」看服务器只验签名不查库的结果。
原因 · 下一步 · 对照原因:服务端没有签发任何访问令牌,客户端也没有刷新令牌。下一步:点「签发访问令牌」,服务器会用密钥对 header.payload 签名,把 sub/role/exp 写进 payload。对照:签发后看「访问令牌」出现三段,刷新令牌单独存。
提示:主操作「签发访问令牌」是唯一的红色按钮;其余按 Tab 顺序可达。重点试三条对照——推进时间到 exp 过期再请求、打开「篡改 payload」再请求、加入黑名单后再请求。
面板已经把每条规则演给你看了,这里把它们命名清楚,并补上无法直接操作的部分。
sub / role / exp),signature 是服务端用密钥对 header.payload 算出的 HMAC。客户端只持有这段字符串,服务端不存它。Authorization: Bearer …,服务端重算签名与 token 自带的 signature 比对,再检查 exp——一致就信任 payload 里的身份,全程不读数据库或会话存储,所以快、能跨服务。/token 端点换新的;被盗风险窗口由 access 的短 exp 控制,refresh token 应单独安全存储且服务端可撤销。从「谁来记状态、要不要跨服务、能不能即时撤销」出发,而不是默认都用 JWT。
Authorization: Bearer … token。两套凭据各自管过期与撤销,承载层交给 cookie 判定。只走这几步,每步都改变服务端可验证的状态或客户端手里的凭据。
{ alg, typ }base64 . { sub, role, exp }base64 计算 HMAC 作为 signature,拼成 header.payload.signature 返回;同时签发一个独立的 refresh token。Authorization: Bearer header.payload.signature,不在 URL 里传。exp 到点一律 401,要求刷新或重新登录。只改一处——偷到 token 后服务端怎么办——结果差很多。这是无状态 token 最该记住的一条。
exp = now + 15m;黑名单 revoke(sig)被偷的 access token 最多用到 exp(几分钟);发现异常时把 signature 写进黑名单,服务端验签后再查黑名单,命中即 401。即便不能像 session 那样瞬时全量失效,窗口也被压到很短。
exp = now + 365d;无黑名单access token 一旦泄漏,在长达一年的 exp 内服务端无从拒绝——因为「无状态」意味着服务端手里根本没有这条 token 的记录。等同于一把长期不换的钥匙,丢了也换不了锁。
你的 access token 有效期 15 分钟、刷新令牌单独存储。攻击者偷到了 access token,但没偷到刷新令牌。15 分钟内你能做的最有效的「止损」是什么?
术语的技术定义和行为以这些一手或权威资料为准。
和本知识点经常一起出现的概念。