作者小头像 Lv.3
350 成长值

个人介绍

这个人很懒,什么都没有留下

感兴趣或擅长的领域

暂无数据
个人勋章
  • 活跃之星
成长雷达
320
30
0
0
0

个人资料

个人介绍

这个人很懒,什么都没有留下

感兴趣或擅长的领域

暂无数据

达成规则

发布时间 2026/10/19 09:08:40 最后回复 早睡早起的Mikey 2026/10/19 12:08:58 版块 开发者空间
29 5 0
他的回复:
JWT 只解决一件事:让服务端在不查库的前提下确认“这串东西是我自己签发的、没被改过”。它是签名,不是加密。 【结构】header.payload.signature 三段。前两段只是 Base64URL,任何人拿到 token 都能直接读出 payload 里的用户 ID、角色、过期时间;第三段才是用密钥算出来的签名(HS256 用对称密钥,RS256 用私钥)。校验时服务端重算一遍签名比对。所以第一条铁律:payload 不要放手机号、身份证、密码这类东西,它等于明文。 【常见的坑,按严重程度排】 1、算法混淆与 alg:none。服务端必须写死“只接受哪一种算法”,绝不能从 header 里的 alg 读。否则把 alg 改成 none,或者把 RS256 降成 HS256、再拿公钥当 HMAC 密钥签名,就能伪造任意身份。 2、密钥太短或可猜。用项目名、域名当 secret 等于没有签名;同时要预留轮换(header 里带 kid,旧密钥保留一段时间),不然泄露只能全量下线。 3、写了 exp 但服务端没校验。exp/nbf/iat 都要手动判,注意单位是秒不是毫秒;只靠前端拦截等于没拦。 4、无状态的真实代价:无法主动作废。改密码、降权、删号都不会让已签发的 token 失效。两种解法:payload 里带版本号或 jti,校验时和当前配置比对(我把 role 写进 token,校验时拿 token 里的 role 和配置里的 role 比一次,配置一改旧 token 自然作废,不用等过期);或者上 Redis 存黑名单,但那就放弃了无状态的好处。 5、存哪里。localStorage 方便,但 XSS 一抖 token 全走;HttpOnly + Secure + SameSite=Lax 的 Cookie 能挡住脚本窃取,但要自己处理 CSRF(最省事的办法是所有写接口要求一个自定义请求头,跨站表单发不出自定义头)。 6、反向代理后 secure cookie 被丢。应用如果以为自己跑在 HTTP 上,下发的 secure cookie 会被浏览器扔掉,现象是“登录成功但刷新又要密码”,很容易查错方向。 7、不校验 aud / iss。同一密钥给多个服务签发时,A 服务的 token 能直接拿去调 B 服务。 8、权限判断写在客户端。前端根据 role 隐藏按钮只是体验,服务端必须再拦一次,否则改一下前端就能越权。 【什么时候不该用 JWT】单体应用、单进程、需要“改密码立即失效”、纯内部接口,直接用服务端 session 更简单也更安全。JWT 的价值在于多服务多实例不共享存储,代价就是上面第 4 条那一堆作废问题。
发布时间 2026/10/19 09:08:40 最后回复 早睡早起的Mikey 2026/10/19 12:08:58 版块 开发者空间
29 5 0
他的回复:
JWT 只解决一件事:让服务端在不查库的前提下确认“这串东西是我自己签发的、没被改过”。它是签名,不是加密。 【结构】header.payload.signature 三段。前两段只是 Base64URL,任何人拿到 token 都能直接读出 payload 里的用户 ID、角色、过期时间;第三段才是用密钥算出来的签名(HS256 用对称密钥,RS256 用私钥)。校验时服务端重算签名比对。所以第一条铁律:payload 不要放手机号、身份证、密码这类东西,它等于明文。 【常见的坑,按严重程度排】 1. 算法混淆和 alg:none。服务端必须写死“只接受哪一种算法”,绝不能从 header 里的 alg 读。否则把 alg 改成 none,或者把 RS256 降成 HS256、再拿公钥当 HMAC 密钥签名,就能伪造任意身份。 2. 密钥太短或可猜。用项目名、域名当 secret 等于没有签名。同时要考虑轮换(header 里带 kid,旧密钥保留一段时间),不然泄露了只能全量下线。 3. 写了 exp 但服务端没校验。exp/nbf/iat 都要手动判,注意单位是秒不是毫秒;只靠前端拦截等于没拦。 4. 无状态的真实代价:无法主动作废。改密码、降权、删号都不会让已签发的 token 失效。两种解法:payload 里带版本号或 jti,校验时和当前配置比对(我把 role 写进 token,校验时拿 token 里的 role 和配置里的 role 比一次,配置一改旧 token 自然作废,不用等过期);或者上 Redis 存黑名单,但那就放弃了无状态的好处。 5. 存哪里。localStorage 方便,但 XSS 一抖 token 全走;HttpOnly + Secure + SameSite=Lax 的 Cookie 能挡住脚本窃取,但要自己处理 CSRF(最省事的办法是所有写接口要求一个自定义请求头,跨站表单发不出自定义头)。 6. 反向代理后面 secure cookie 被丢。应用如果以为自己跑在 HTTP 上,下发的 secure cookie 会被浏览器扔掉,现象是“登录成功但刷新又要密码”,很容易查错方向。 7. 不校验 aud / iss。同一密钥给多个服务签发时,A 服务的 token 能直接拿去调 B 服务。 8. 权限判断写在客户端。前端根据 role 隐藏按钮只是体验,服务端必须再拦一次,否则改一下前端就能越权。 【什么时候不该用 JWT】单体应用、单进程、需要“改密码立即失效”、纯内部接口,直接用服务端 session 更简单也更安全。JWT 的价值在于多服务多实例不共享存储,代价就是上面第 4 条那一堆作废问题。