JWT 鉴权常见知识点及参考答案
JWT 鉴权常见知识点及参考答案
最近在 Go Web 项目当中使用到了 JWT 进行鉴权,因此通过这篇文章对 JWT 的原理及相关的知识点进行总结。
文章目录
- JWT 鉴权常见知识点及参考答案
- JWT 签名算法的详细工作流程
- 一. 签名的生成过程
- 二. 签名的验证过程
- 1. 什么是 JWT?它的结构是什么?
- 2. JWT 的工作原理(流程)是什么?
- 3. JWT 的优缺点?
- 4. 如何防止 JWT 被篡改?
- 5. JWT 应该存储在客户端哪里?Cookie 还是 LocalStorage?
- 什么是 Cookie?什么是 LocalStorage?二者对比?
- Cookie
- 什么是 CSRF 攻击?
- LocalStorage
- Cookie 与 LocalStorage 的关键区别
- JWT 存储建议
- 拓展:何时使用 Cookie 和 LocalStorage
- 6. 如何实现 JWT 的主动失效?
- 7. JWT 和 Session 的区别?
- 8. 什么是 Refresh Token?它的作用是什么?
- 9. JWT 可能的安全风险有哪些?如何防御?
- 10. 什么场景适合使用 JWT?什么场景不适合?
- 11. JWT 的 Payload 可以被解密吗?
- 12. 如何选择 HS256 和 RS256?
- 13. JWT 中的签名算法 HS256 和 RS256 有什么区别?在什么场景下应该选择哪种算法?
- 14. 如何在微服务架构中使用 JWT 进行服务间的安全通信?
- 15. JWT 的 Payload 应该避免存储哪些类型的用户数据?为什么?
- 16. 除了 JWT 之外,还有哪些鉴权方法?为什么 JWT 更好?
- Session-Cookie 鉴权
- OAuth 2.0 / OpenID Connect(OIDC)
- 为什么 JWT 更好?
- JWT 的局限性
在开始正式深入知识点之前,我们需要先回顾一下 JWT 的工作原理:
JWT 签名算法的详细工作流程
一. 签名的生成过程
步骤一:拼接 Header 和 Payload
分别对 JWT 的 Header(保存所使用的加密算法及 Token 类型【也就是 JWT】) 和 Payload(包括一些标识用户个人信息的字段)进行 Base64Url 编码,得到两个字符串。用 .
连接两个字符串,形成待签名的原始数据:
base64UrlEncode(Header) + "." + base64UrlEncode(Payload)
步骤二:使用密钥和算法生成签名
基于 Header 中指定的算法(如 HS256 或 RS256),用密钥对拼接后的原始数据进行加密,生成签名:
HMACSHA256(
base64UrlEncode(Header) + "." + base64UrlEncode(Payload),
SecretKey
)
// OR
RSASHA256(
base64UrlEncode(Header) + "." + base64UrlEncode(Payload),
PrivateKey
)
步骤三:组合完整的 JWT
对生成的签名使用 Base64Url 编码,并与 Header.Payload
通过 .
拼接,得到完整的 JWT:
Header.Payload.Signature
上面三个部分均通过 Base64Url 编码,Signature 在编码前还进行了加密。
二. 签名的验证过程
服务端接收到来自客户端的 JWT 之后,按照以下步骤验证签名的合法性:
- 解析 Header 和 Payload,并从 Header 中获取编码 Signature 所用到的具体的加密算法(HS256/RS256)。在这一步中通过解析 Payload 中可能包含的过期时间可以得知当前 JWT 是否有效;
- 重新计算签名:使用相同的加密算法 +
Header.Payload
+ 密钥,重新计算 Signature; - 比对签名:将新生成的签名与 JWT 中的签名进行对比。一致则 Token 未被篡改,验证通过;否则 Token 可能被篡改,验证不通过。
下面我们来看一些与 JWT 相关的问题。
1. 什么是 JWT?它的结构是什么?
JWT(JSON Web Token)是一种开放标准(RFC 7519),是用于在网络间安全传输声明(Claims)的轻量级对象。
JWT 的结构包括:
- Header:用于描述加密算法(如 HS256、RS256)和 Token 类型(如 JWT);
- Payload:存放实际数据(如用户 ID 和过期时间);
- Signature:对 Header 和 Payload 进行签名,防止篡改。
2. JWT 的工作原理(流程)是什么?
- 登录:用户发送登录凭证(如用户名 + 密码)到服务端;
- 生成 Token(由服务端):服务端接收到来自用户发送的凭证之后,对凭证进行验证,然后生成 JWT 回发给用户。
- 存储 Token(由客户端):用户客户端(如浏览器)存储 JWT(LocalStorage/Cookie)。
- 携带 Token(当客户端再次向服务端发送请求时):后续客户端发送给服务端的请求将在
Authorization: Bearer <token>
中携带 token。 - 验证 Token(由服务端):服务端对客户端携带的 token 进行解析,从中解析出签名和 Token 有效期,如果 token 的签名非法,或有效期已过,那么验证失败。否则验证成功,并授权客户端访问资源。
- 如果验证成功,之前由服务端分发的 JWT 通常存储着用户的 ID,那么服务端在此时就可以得知这条请求客户端的个人信息,服务端可以对这种信息进行存储,以在处理一次 HTTP Request 期间使用用户信息。
3. JWT 的优缺点?
优点
- 无状态:服务端无需存储会话信息,适合分布式系统。
- 跨域支持:适用于微服务或跨域场景(如 OAuth2)。
- 自包含:Payload 可包含用户信息,从而减少数据库查询操作。
缺点
- 无法主动失效:除非设置短有效期或额外逻辑(如黑名单)。
- 性能问题:Token 较大会增加网络开销。
- 安全性依赖存储:客户端存储不当被 XSS 攻击窃取。
4. 如何防止 JWT 被篡改?
- 签名机制:服务端用密钥生成签名,任何篡改都会导致签名不匹配。
- 强算法:避免使用
none
算法,优先使用 HS256 / RS256。 - 密钥保护:确保密钥不被泄露。
5. JWT 应该存储在客户端哪里?Cookie 还是 LocalStorage?
在回答这个问题之前,我们先来了解一下 Cookie 和 LocalStorage。
什么是 Cookie?什么是 LocalStorage?二者对比?
Cookie
定义
Cookie 是由服务器生成并发送到客户端(比如浏览器)的小型文本文件,用于存储会话信息、用户偏好数据等。每次客户端向服务器发送请求时,Cookie 会自动附加在 HTTP 头部当中。
特点
- 存储容量:单个 Cookie 约 4 KB,每个域名下最多允许约 20 ~ 50 个 Cookie。
- 生命周期:分为会话 Cookie 和持久 Cookie。前者在浏览器关闭时失效,后者通过 Expires 或 Max-Age 设置过期时间。
- 作用域:Domain 指定哪些域名可以访问 Cookie,Path 限制 Cookie 在特定路径下有效。
- 安全性:仅通过 HTTPS 传输(Secure);禁止 JavaScript 访问,避免 XSS 攻击(禁止 JS 访问的特性就是 HTTPOnly);SameSite:限制跨站携带 Cookie,防御 CSRF 攻击。
用途
- 保存用户登录状态(如 Session ID 或 JWT)。
- 追踪用户行为(用于广告定向)。
- 保存个性化设置(如语言、主题)。
什么是 CSRF 攻击?
CSRF(跨站请求伪造)攻击是一种利用用户已登录的身份,在用户不知情的情况下,诱使其执行非预期操作的网络攻击方式。
LocalStorage
定义
LocalStorage 是 HTML5 提供的浏览器本地存储 API,属于 Web Storage 规范。数据以键值对形式永久存储在客户端,除非手动清楚或通过代码清楚。
特点
- 存储容量:约 5 ~ 10 MB。
- 生命周期:永久存储,除非用户清楚浏览器缓存或开发者主动删除。
- 作用域:遵循同源策略,仅同域名、协议、端口的页面可访问。
- 安全性:无自动加密,数据明文存储。易受 XSS 攻击:JavaScript 直接读写 LocalStorage。
用途
- 存储客户端非敏感数据(如用户界面配置)。
- 缓存静态资源信息(如图片、脚本)。
- 单页应用(SPA)的持久化管理。
Cookie 与 LocalStorage 的关键区别
JWT 存储建议
Cookie
- 优点:支持 HTTPOnly 和 Secure 标志,防止 XSS 攻击。
- 缺点:可能受 CSRF 攻击。
LocalStorage
- 优点:容量大,同源策略保护。
- 缺点:易受 XSS 攻击直接读取,因为 LocalStorage 不经加密明文存储在客户端。
推荐
使用 Cookie 更安全,但需要结合防御策略(如 SameSite 属性,从而避免 CSRF)。
拓展:何时使用 Cookie 和 LocalStorage
- Cookie:用于需要会话管理、身份验证,且需要重视安全性的场景。
- LocalStorage:存储纯客户端数据(如 UI 主题)、大容量非敏感信息,或需长期保存的数据。
6. 如何实现 JWT 的主动失效?
- 黑名单机制:服务端维护一个失效了的 Token 列表(缺点是牺牲了 JWT 的无状态性,无状态性指的是服务端不需要对 JWT 进行存储)。
- 短期 Token:设置短有效期,搭配 Refresh Token 续期。
- 版本控制:用户登出时更新密钥或用户 Token 的版本号。
7. JWT 和 Session 的区别?
JWT | Session |
---|---|
无状态,数据存储在 Token 当中 | 有状态,数据在服务端存储 |
适合分布式系统 | 需会话存储集群同步 |
跨域支持良好 | 依赖 Cookie 域/路径限制 |
需处理 Token 过期和撤销逻辑 | 直接删除服务端会话即失效 |
8. 什么是 Refresh Token?它的作用是什么?
Refresh Token 是长期有效的 Token(存储于服务端),由认证服务器在用户首次登录或授权时颁发,专门用于获取新的 Access Token。
作用
- Access Token 过期后,客户端用 Refresh Token 申请新的 Token。
- 减少 Access Token 的泄露风险(因有效期短)。
- Refresh Token 仅用于获取新的 Access Token,不直接访问业务接口。服务端可吊销 Refresh Token 强制用户重新登录。
9. JWT 可能的安全风险有哪些?如何防御?
风险
- XSS 攻击窃取存储在 LocalStorage 当中的 Token。
- 弱加密算法(如使用 HS256 但密钥强度不足)。
- Payload 中存储敏感信息(如密码)。
防御
- 使用 HTTPOnly Cookie + CSRF Token。
- 选择 RS256 替代 HS256,前者是非对称加密。
- 避免在 Payload 中存放敏感数据。
10. 什么场景适合使用 JWT?什么场景不适合?
适合
- 跨服务认证(如微服务间调用)。
- 第三方授权(如 OAuth2)。
- 一次性验证(如密码重置链接)。
不适合
- 需要实时吊销权限(如后台强制踢人)。
- 传输敏感信息(需要配合 JWE 加密)。
- 客户端无法安全存储 Token 时不适合使用 JWT。
11. JWT 的 Payload 可以被解密吗?
Payload 使用 Base64URL 编码,可以直接解码,但未被加密。如果需要保密,需要使用 JWE(JSON Web Encryption)。
12. 如何选择 HS256 和 RS256?
- HS256 使用共享密钥,适合单体服务;
- RS256 使用公私钥,适合多服务场景。
13. JWT 中的签名算法 HS256 和 RS256 有什么区别?在什么场景下应该选择哪种算法?
HS256
- 使用对称加密,服务端和客户端共享同一个密钥生成和验证签名。
- 优点:计算速度快,适合单体服务架构。
- 缺点:密钥需要严格保护,若泄露则系统完全暴露。
RS256
- 使用非对称加密,服务端用私钥签名,客户端用公钥验证。
- 优点:公钥可公开分发,适合多服务协作(如微服务、第三方认证)。
- 缺点:计算开销大。
场景
- 单体服务:HS256。
- 分布式系统或需公钥验证的场景:RS256。
14. 如何在微服务架构中使用 JWT 进行服务间的安全通信?
- 统一认证服务(Auth Service):负责颁发 JWT,各服务信任该服务的签名。
- Token 传递:请求到达网关或首个服务时验证 JWT,随后透传 Token 至下游服务。
- 权限控制:在 JWT 的 Payload 中声明用户角色和权限,各服务根据此信息授权。
- 服务间调用:服务 A 调用服务 B 时,携带原始 JWT 或生成新的服务间 Token。
- 防御重放攻击:在 Token 中加入唯一标识或时间戳,服务端记录已经使用的 Token 标识。
15. JWT 的 Payload 应该避免存储哪些类型的用户数据?为什么?
避免存储的数据
- 敏感信息:因为 JWT Payload 仅 Base64 编码,未加密,易泄露;
- 过大的数据:增加 Token 体积,影响网络传输性能;
- 动态变化的数据:Token 一旦签发则无法实时更新,导致数据不一致。
建议存储的数据
- 用户唯一标识(比如 user_id);
- 角色、权限;
- Token 有效期。
16. 除了 JWT 之外,还有哪些鉴权方法?为什么 JWT 更好?
除了 JWT 之外,还包括以下鉴权方法:
Session-Cookie 鉴权
原理
- 用户登录后,服务端生成 Session ID 并存储在服务端(如数据库、Redis)。
- 通过 Set-Cookie 头部将 Session ID 放松到客户端浏览器。
- 后续请求自动携带 Cookie,服务端通过 Session ID 验证用户身份。
特点
- 有状态:服务端需维护 Session 存储。
- 安全性依赖 Cookie 属性。
适用场景
传统单服务架构,需严格控制会话状态的系统(如银行后台)。
OAuth 2.0 / OpenID Connect(OIDC)
原理
- OAuth 2.0 专注于授权(如第三方应用访问用户资源)。
- OIDC 在 OAuth 2.0 基础上扩展,提供身份认证功能(返回用户信息的 ID Token)。
- 用户通过授权服务器(如 Google、GitHub)登录,获取 Access Token 访问资源。
特点
- 适合第三方集成。
- 复杂:涉及多个角色(资源服务器、授权服务器、客户端)。
适用场景
跨平台应用、第三方服务授权。
为什么 JWT 更好?
JWT 并非在所有场景下都是最佳选择,但是相较于上述认证方式,JWT 具有以下优点:
- 无状态性:服务端无需存储会话信息,天然适合分布式系统和微服务架构。基于 JWT 无状态的特点,JWT 鉴权降低了服务端的存储压力,避免 Session 同步问题(如 Redis 集群故障)。
- 跨域和跨服务支持:JWT 可以通过 HTTP 头部(
Authorization: Bearer <token>
)轻松跨域传递,适合前后端分离和多服务协作场景。 - 自包含性:JWT 的 Payload 字段可以直接携带用户信息,减少数据库查询操作。自包含性使得 JWT 适合一次性操作或离线验证。
JWT 的局限性
- 无法主动吊销:除非使用黑名单(失去无状态性)或设置 JWT 的短有效期(推荐结合 Refresh Token);
- Token 膨胀:Payload 存储过多字段会增加网络负担;
- 密钥管理:HS256 共享密钥或 RS256 私钥需要严格保护。