目录
- 前言
- [方案一:JWT + Spring Security(最常用)](#方案一:JWT + Spring Security(最常用))
-
- 1.登录
- 2.请求
- 3.Gateway统一校验
- 4.Gateway过滤器
- 5.微服务是否还要校验?
- 6.Token过期怎么办
- [7.Access Token + Refresh Token](#7.Access Token + Refresh Token)
-
- [Access Token](#Access Token)
- [Refresh Token](#Refresh Token)
- [方案二:OAuth2 标准方案](#方案二:OAuth2 标准方案)
- 方案三:国内项目常用:Sa-Token
- 方案四:证券行业推荐架构
前言
Spring Boot 或者 Spring Cloud 微服务架构中最常见的认证授权场景。
需求场景:
- 用户登录后颁发 Token
- 所有微服务校验 Token
- Token 过期自动续签
- 微服务之间调用传递用户身份
目前主流方案有:
| 方案 | 推荐度 | 适用场景 |
|---|---|---|
| JWT + Spring Security | ★★★★★ | 最常见 |
| OAuth2 + Spring Authorization Server | ★★★★★ | 企业级标准方案 |
| Sa-Token | ★★★★★ | 国内项目非常流行 |
| Apache Shiro | ★★ | 老项目较多 |
| Session共享(Redis) | ★★ | 单体项目较多 |
对于 Spring Cloud 项目,现在最主流的是:
Spring Security + JWT + Gateway
或者
Spring Authorization Server + OAuth2 + JWT
方案一:JWT + Spring Security(最常用)
架构:
text
登录
+-------------+
| auth-service |
+-------------+
|
| 生成JWT
▼
eyJhbGciOiJIUzI1NiJ9...
|
▼
浏览器/APP保存Token
|
▼
Gateway
|
▼
user-service order-service
1.登录
用户登录:
http
POST /login
{
"username":"admin",
"password":"123456"
}
认证成功:
json
{
"token":"xxxxx.yyyyy.zzzzz"
}
JWT内容:
json
{
"userId":1001,
"username":"admin",
"role":"ADMIN",
"exp":1750000000
}
2.请求
http
GET /user/info
Authorization: Bearer xxxxx.yyyyy.zzzzz
3.Gateway统一校验
不要每个微服务都校验。
一般放在 Gateway。
text
用户
↓
Gateway
↓
UserService
↓
OrderService
流程:
text
请求
↓
Gateway
↓
解析JWT
↓
验证签名
↓
验证过期时间
↓
放行
失败:
json
{
"code":401,
"msg":"token已失效"
}
4.Gateway过滤器
例如:
java
@Component
public class JwtFilter implements GlobalFilter {
@Override
public Mono<Void> filter(
ServerWebExchange exchange,
GatewayFilterChain chain) {
String token = exchange
.getRequest()
.getHeaders()
.getFirst(HttpHeaders.AUTHORIZATION);
if(token == null){
throw new RuntimeException("未登录");
}
JwtUtil.parse(token);
return chain.filter(exchange);
}
}
这样所有微服务自动生效。
5.微服务是否还要校验?
有两种做法。
做法1
只在Gateway校验
text
用户
↓
Gateway
↓
UserService
优点:
性能高
缺点:
绕过Gateway直接访问服务有风险
做法2(推荐)
Gateway校验一次
微服务再校验一次
text
用户
↓
Gateway
↓
UserService
↓
再次校验JWT
银行、证券、支付系统通常这样做。
你在证券行业,建议采用这种模式。
6.Token过期怎么办
JWT天然有过期时间:
java
Jwts.builder()
.setExpiration(
new Date(System.currentTimeMillis()+3600_000)
)
例如:
text
1小时过期
问题来了
用户操作到59分钟时:
text
突然过期
体验很差。
所以需要:
text
Access Token + Refresh Token
7.Access Token + Refresh Token
登录:
json
{
"accessToken":"xxx",
"refreshToken":"yyy"
}
Access Token
有效期:
text
30分钟
Refresh Token
有效期:
text
7天
流程:
text
用户请求
↓
Access Token过期
↓
401
↓
前端调用
/auth/refresh
↓
携带Refresh Token
↓
认证中心
↓
签发新的Access Token
用户无感知。
方案二:OAuth2 标准方案
大厂一般:
text
Authorization Server
+
Resource Server
Spring 官方方案:
- Spring Security
- Spring Authorization Server
架构:
text
+------------------+
| Authorization |
| Server |
+------------------+
|
签发JWT
|
+---------+ +---------+
| UserSvc | |OrderSvc |
+---------+ +---------+
认证中心负责:
text
登录
签发Token
刷新Token
注销Token
业务系统负责:
text
校验Token
读取用户信息
职责非常清晰。
方案三:国内项目常用:Sa-Token
如果你不想写一堆 Spring Security 配置。
推荐:
特点:
text
比Spring Security简单
支持JWT
支持Redis
支持单点登录
支持权限控制
支持踢人下线
支持Token续签
登录:
java
StpUtil.login(userId);
获取Token:
java
String token = StpUtil.getTokenValue();
校验:
java
StpUtil.checkLogin();
非常简单。
很多国内中后台项目都在使用。
方案四:证券行业推荐架构
如果目前的技术栈是Spring Boot + Spring Cloud:
text
Gateway
│
▼
auth-service
│
┌──────────────┼──────────────┐
▼ ▼ ▼
user-service order-service trade-service
│
▼
Redis
认证方案:
text
Spring Security
+ JWT
+ Redis
+ Gateway
Token设计:
text
Access Token
30分钟
Refresh Token
7天
流程:
text
登录
↓
auth-service签发Token
↓
Gateway校验
↓
微服务二次校验
↓
过期
↓
Refresh Token换新Token
这是目前绝大多数金融、证券、银行类 Spring Cloud 系统采用的模式。
其他建议深入理解的:
- Spring Security 认证流程
- JWT 的组成与签名原理
- OAuth2 四种授权模式
- Spring Authorization Server
- Gateway 统一鉴权
- Refresh Token 续签机制
- 单点登录(SSO)
- Redis 黑名单 Token
- 用户强制下线实现原理