什么是 JWT
What is JWT
一句话:JSON Web Token —— 一个自带签名的字符串, 服务器不用存它也能验证它没被篡改。
三段结构,用点分隔:header.payload.signature
- header—— 用什么算法签的
- payload—— 用户 id、过期时间等业务数据
- signature—— 对前两段用密钥算出的签名
最重要的一条(必答):前两段只是Base64URL 编码,不是加密——任何人都能解出来看。 所以payload 里绝不能放密码、 身份证号这类敏感信息。 签名保证的是「没被改过」,不是「看不到」。
优点:无状态—— 服务器不用存 session, 天然适合多实例和微服务 (任何一台都能独立验证)。
缺点(这半边是重点):
- 没法主动失效。签出去就有效到过期。 用户改密码、 管理员封号,旧 token 照样能用。
- 体积比 session id 大, 每个请求都要带。
- 放哪都有风险——
localStorage怕 XSS, cookie 怕 CSRF。
会追问:「怎么让 JWT 提前失效?」—— 这是这题的分水岭:
- 短过期 + refresh token—— access token 只活 15 分钟, 用一个可撤销的 refresh token 换新的。这是标准做法。
- 黑名单—— 把要作废的 token id 存 Redis。但这就重新变成有状态了, 等于放弃了 JWT 的主要优点。
安全上还有一个经典坑:验证时必须指定期望的算法, 不能信 header 里写的 —— 否则攻击者把 alg改成 none 就绕过签名了。
In one line: a JSON Web Token is a string that carries its own signature, so the server can verify it has not been tampered with without storing it.
Three parts, separated by dots: header.payload.signature
- header — which algorithm signed it
- payload — the data: user id, expiry and so on
- signature — the first two parts signed with your secret
The one thing you must say: the first two parts are Base64URL encoded, not encrypted — anyone can decode and read them. So never put a password or a national id number in the payload. The signature guarantees “unchanged”, not “unreadable”.
The upside: it is stateless — the server stores no session, which suits many instances and microservices, since any one of them can verify it alone.
The downsides — this half is the real question:
- You cannot revoke it. Once issued it is valid until it expires. User changes their password, an admin bans the account — the old token still works.
- It is bigger than a session id and rides along on every request.
- Every place you store it has a risk —
localStorageis exposed to XSS, a cookie is exposed to CSRF.
Follow-up: “How do you expire a JWT early?” — this is where the question separates people:
- Short expiry plus a refresh token — the access token lives 15 minutes and you trade a revocable refresh token for a new one. This is the standard answer.
- A blocklist — keep revoked token ids in Redis. But now you are stateful again, which gives up the main reason you chose JWT.
One classic security trap: when you verify, you must pin the algorithm you expect rather than trust the one in the header — otherwise an attacker sets alg to none and walks past the signature entirely.