深入浅出认证与授权:从核心概念到 OAuth2 实战
一文打通认证授权知识体系,读懂 RBAC、JWT、OAuth2.与微服务安全架构
引言
逛淘宝时,你需要登录(认证),然后系统根据你是普通用户还是 VIP 决定能否查看专属优惠(授权)。小到一个 H5 页面,大到复杂的企业级应用,认证与授权都是不可或缺的模块。
在软件系统设计中,如何让应用在各种环境中安全、高效地访问资源,涉及一系列概念与细分领域:
- 认证(Authentication) :系统识别合法用户,解决“你是谁”的问题。
- 授权(Authorization) :用户认证通过后,系统判断“你能做什么”。
- 凭证(Credential) :双方约定的身份证明,保证意图真实、完整、不可抵赖。
- 保密(Secrecy) :安全持久化账户信息,防止窃取与滥用。
- 会话(Session) :避免每次操作都重新认证,保持登录状态。
本文将围绕这些核心概念,从基础模型讲到微服务架构下的 OAuth2 + JWT 实践,助你构建完整的认证授权知识体系。
一、核心概念详解
1.1 认证(Authentication)
认证是识别合法用户的过程。常见方式:
- 用户名 + 密码(最普遍)
- 手机短信验证码
- 二维码扫码登录(如微信)
- CA 数字证书认证
一句话:认证回答“你是谁”。
1.2 授权(Authorization)
授权是用户通过认证后,系统根据其权限控制资源访问的过程。常见访问控制模型:
| 模型 | 全称 | 核心思想 | 适用场景 |
|---|---|---|---|
| ACL | 访问控制列表 | 直接为每个用户或资源设置权限列表 | 文件系统、网络设备(如 Linux getfacl) |
| RBAC | 基于角色的访问控制 | 引入“角色”,将权限赋予角色,再把角色赋予用户 | 大部分业务系统,如管理后台、CRM |
| ABAC | 基于属性的访问控制 | 通过用户属性、资源属性、环境属性动态计算权限 | 复杂场景,如:仅允许在工作时间访问敏感数据 |
| OAuth2 | 开放授权框架 | 第三方应用获取用户授权令牌,无需用户密码 | 接入微信/QQ登录、开放平台 API |
RBAC 示意图:
用户(User) → 角色(Role) → 权限(Permission) → 资源(Resource)
本质:所有模型都解决“谁(User)拥有什么权限(Authority)操作哪些资源(Resource)”。
在 Spring Security 中,权限控制模型通常如下:
UserDetails → GrantedAuthority → @PreAuthorize("hasAuthority('ROLE_ADMIN')")
1.3 凭证(Credential)与会话(Session)
HTTP 是无状态的,认证后需要维持会话,避免每次请求都重新登录。
传统方案:Cookie-Session
- 服务端存储 Session(通常内存或 Redis),客户端存储 SessionId(Cookie)。
- 优点:成熟、简单。
- 缺点:分布式环境下 Session 共享困难。
集群环境下的三种 Session 处理方式:
| 方式 | 原理 | 优缺点 |
|---|---|---|
| 中心化存储 | Session 存入 Redis 等中间件 | 性能好,但须保证中间件高可用 |
| 会话复制 | 节点间广播复制 Session | 网络开销大,不推荐大规模集群 |
| 会话粘滞 | 负载均衡将同一用户始终路由到同一节点 | 节点宕机会丢失会话 |
Token 机制(无状态)
- 客户端存储 Token(如 LocalStorage),服务端不保存会话。
- 常用 JWT(JSON Web Token)。
- 优点:天然适合分布式、可扩展。
- 缺点:无法主动失效(除非借助黑名单缓存)。
JWT 结构:Header.Payload.Signature
- Header:令牌类型(JWT)和签名算法(如 HS256、RS256)。
- Payload:声明数据(用户 ID、过期时间等)。
- Signature:对前两部分签名,防篡改。
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
二、认证与授权方案的发展与迭代
2.1 单体应用时代
- 使用 Session-Cookie,依赖应用服务器内存。
- 权限校验通常在 Filter/Interceptor 中完成。
- 优点:简单、低延迟。缺点:无法水平扩展。
2.2 负载均衡 / 集群架构
- 引入 Redis 中心化存储 Session。
- 或采用 JWT 无状态 Token。
- Spring Session 等项目简化了集成。
2.3 微服务架构
- 每个服务独立,且可能有不同的认证授权需求。
- 典型方案:OAuth2 + JWT + 网关统一认证。
- 认证中心(Authorization Server)颁发 Token,资源服务校验 Token。
- 网关层可集中进行 Token 解析和权限校验,减少重复代码。
三、OAuth 2.0 详解
OAuth 2.0 是一个授权框架,允许第三方应用获取用户授权后访问其资源,而无需用户提供密码。它不是向后兼容 OAuth 1.0 的升级,而是一个全新设计。
核心角色:
- Resource Owner:资源所有者,即用户。
- Client:第三方应用(如网站 A 要访问用户存储在网站 B 的照片)。
- Authorization Server:认证服务器,负责颁发令牌。
- Resource Server:资源服务器,持有用户资源(可与认证服务器同一,也可分离)。
OAuth 2.0 定义了四种授权方式,信任度由低到高:
| 模式 | 适用场景 | 特点 |
|---|---|---|
| 授权码模式 | 有后端的 Web 应用 | 最安全、最常用 |
| 简化模式(Implicit) | 纯前端应用(如 SPA) | 无中间代码交换,直接返回令牌(已不推荐) |
| 密码模式 | 高度信任的客户端(如官方 App) | 用户提供用户名密码给客户端,换取令牌 |
| 客户端模式 | 客户端以自己的名义访问资源 | 无需用户参与,适用于服务器间调用 |
3.1 授权码模式(Authorization Code)
这是最完整、最安全的模式,流程如下:
1. 客户端重定向用户到认证服务器:
https://b.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read
2. 用户同意授权后,认证服务器重定向回客户端,并附带授权码:
https://a.com/callback?code=AUTHORIZATION_CODE
3. 客户端使用授权码向认证服务器换取令牌:
POST https://b.com/oauth/token
grant_type=authorization_code&code=AUTHORIZATION_CODE&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
4. 认证服务器返回 access_token(和可选的 refresh_token)
3.2 简化模式(Implicit)
省略授权码步骤,直接返回令牌(常用于纯前端应用)。现已因安全原因被 OAuth 2.1 废弃,建议改用授权码 + PKCE。
3.3 密码模式(Resource Owner Password Credentials)
用户直接在客户端输入用户名密码,客户端用这些凭证换取令牌。只适用于客户端和资源所有者高度信任的场景(如官方移动 App)。
请求示例:
POST https://oauth.b.com/token
grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
响应直接返回令牌。
3.4 客户端模式(Client Credentials)
客户端以自己的名义申请令牌,没有用户参与。通常用于后端服务之间的授权。
请求示例:
POST https://oauth.b.com/token
grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
四、Spring Security OAuth2 + 网关实践
在微服务架构中,通常使用 Spring Security OAuth2(现已迁移到 Spring Authorization Server)实现认证中心,配合 Spring Cloud Gateway 实现统一认证。
4.1 两种主流架构思路
| 思路 | 描述 | 优点 | 缺点 |
|---|---|---|---|
| 网关只做转发 | 网关将请求直接转发到各资源服务,每个资源服务单独验证 Token(远程调用认证服务器) | 隔离性好 | 每次请求都需远程调用 UAA,认证服务器压力大 |
| 网关统一验证 | 网关集中验证 Token(如本地解析 JWT),并转发请求,资源服务不再验证 | 性能高,减少网络开销 | 网关成为关键节点,需高可用 |
4.2 JWT + 网关模式推荐
- 认证服务器生成 JWT 令牌(使用 RSA 私钥签名)。
- 网关配置公钥,解析并验证 JWT 签名,同时可将用户信息注入请求头(如
X-User-Id)。 - 资源服务接收请求,直接从请求头获取用户信息,无需再次验证。
优点:
- 无状态,水平扩展容易。
- 网关性能瓶颈可控(仅做签名验证,无远程调用)。
- Token 中可携带用户角色信息,实现细粒度权限控制。
缺点:
- JWT 一旦签发,无法主动失效(除非引入黑名单缓存)。
- Token 体积较大,若携带过多 Claim 会增大网络开销。
五、总结与最佳实践
| 场景 | 推荐方案 |
|---|---|
| 单体应用 | Session-Cookie + RBAC |
| 集群/分布式 | JWT 无状态 Token 或 Redis 会话 |
| 开放 API 给第三方 | OAuth2 授权码模式 |
| 微服务内部服务间调用 | OAuth2 客户端模式 或 JWT + 网关验证 |
| 前后端分离 SPA | OAuth2 授权码 + PKCE(替代简化模式) |
安全提醒:
- 永远不要在客户端存储敏感凭证(如用户密码)。
- JWT 尽量设置较短有效期,搭配 refresh_token 使用。
- 敏感接口应使用 HTTPS,防止中间人攻击。
参考文档
如果本文对您有帮助,欢迎点赞、收藏、转发,让更多人了解认证与授权的精髓。