190 lines
5.2 KiB
Markdown
190 lines
5.2 KiB
Markdown
# OAuth2/OIDC 统一认证系统
|
||
|
||
这是一个基于Spring Boot的多服务架构,使用OAuth2和OIDC实现统一认证。
|
||
|
||
## 系统架构
|
||
|
||
```
|
||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||
│ 前端应用 │ │ 网关服务 │ │ 资源服务 │
|
||
│ (a.sun.com) │───▶│ (8080) │───▶│ (8081) │
|
||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||
│ │ │
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||
│ OIDC服务器 │ │ JWT验证 │ │ 受保护资源 │
|
||
│ (9000) │ │ Token转发 │ │ API端点 │
|
||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||
```
|
||
|
||
## 服务组件
|
||
|
||
### 1. OIDC授权服务器 (oidc/)
|
||
- **端口**: 9000
|
||
- **功能**: OAuth2/OIDC授权服务器
|
||
- **客户端配置**:
|
||
- 客户端ID: `a-client`
|
||
- 客户端密钥: `a-secret`
|
||
- 重定向URI: `http://a.sun.com/callback`
|
||
- 授权类型: `authorization_code`, `refresh_token`
|
||
- 作用域: `openid`, `read`
|
||
|
||
### 2. 网关服务 (gateway/)
|
||
- **端口**: 8080
|
||
- **功能**: API网关,JWT验证,Token转发
|
||
- **特性**:
|
||
- JWT Token验证
|
||
- 路由转发到后端服务
|
||
- Token Relay功能
|
||
|
||
### 3. 资源服务 (resourceservice/)
|
||
- **端口**: 8081
|
||
- **功能**: 后端API服务
|
||
- **端点**: `/api/resource` (GET)
|
||
|
||
### 4. 前端应用 (resourceservicehtml/)
|
||
- **域名**: a.sun.com
|
||
- **功能**: 用户界面,OIDC登录流程
|
||
- **页面**:
|
||
- `index.html`: 主页面,包含登录和API调用功能
|
||
- `callback.html`: OIDC回调处理页面
|
||
- `test.html`: 配置测试页面
|
||
|
||
## 认证流程
|
||
|
||
### 1. 用户登录流程
|
||
1. 用户访问 `http://a.sun.com`
|
||
2. 前端检查本地Token
|
||
3. 如果没有Token,重定向到OIDC登录页面
|
||
4. 用户在OIDC服务器登录
|
||
5. OIDC服务器重定向回 `http://a.sun.com/callback`
|
||
6. 前端用授权码交换Token
|
||
7. Token保存到本地存储
|
||
|
||
### 2. API调用流程
|
||
1. 前端使用Token调用 `/api/resource`
|
||
2. 请求经过nginx代理到网关
|
||
3. 网关验证JWT Token
|
||
4. 网关转发请求到资源服务
|
||
5. 资源服务返回数据
|
||
|
||
## 配置说明
|
||
|
||
### OIDC服务器配置
|
||
- 使用内存存储用户和客户端
|
||
- 默认用户: `user/password`
|
||
- RSA密钥对用于JWT签名
|
||
|
||
### 网关配置
|
||
- WebFlux架构
|
||
- JWT Token验证
|
||
- 路由配置指向资源服务
|
||
|
||
### 前端配置
|
||
- OIDC客户端配置
|
||
- Token本地存储
|
||
- 状态参数防CSRF攻击
|
||
|
||
## 启动顺序
|
||
|
||
1. **启动OIDC服务器**:
|
||
```bash
|
||
cd oidc
|
||
mvn spring-boot:run
|
||
```
|
||
|
||
2. **启动网关服务**:
|
||
```bash
|
||
cd gateway
|
||
mvn spring-boot:run
|
||
```
|
||
|
||
3. **启动资源服务**:
|
||
```bash
|
||
cd resourceservice
|
||
mvn spring-boot:run
|
||
```
|
||
|
||
4. **配置nginx**:
|
||
```bash
|
||
sudo cp resourceservicehtml/nginx.conf /opt/homebrew/etc/nginx/nginx.conf
|
||
sudo nginx -s reload
|
||
```
|
||
|
||
5. **配置hosts**:
|
||
```
|
||
127.0.0.1 a.sun.com
|
||
127.0.0.1 oidc.sun.com
|
||
```
|
||
|
||
## 测试
|
||
|
||
### 1. 访问前端
|
||
- 主页: `http://a.sun.com`
|
||
- 测试页面: `http://a.sun.com/test.html`
|
||
|
||
### 2. 测试OIDC端点
|
||
- JWKS: `http://localhost:9000/oauth2/jwks`
|
||
- 授权端点: `http://localhost:9000/oauth2/authorize`
|
||
- Token端点: `http://localhost:9000/oauth2/token`
|
||
|
||
### 3. 测试API
|
||
- 资源API: `http://a.sun.com/api/resource`
|
||
|
||
## 安全特性
|
||
|
||
- JWT Token验证
|
||
- 状态参数防CSRF攻击
|
||
- HTTPS重定向支持
|
||
- Token过期处理
|
||
- 刷新Token机制
|
||
|
||
## 故障排除
|
||
|
||
### 常见问题
|
||
|
||
1. **OIDC发现端点无法访问**
|
||
- 检查OIDC服务器是否启动
|
||
- 验证安全配置
|
||
|
||
2. **Token验证失败**
|
||
- 检查Token是否过期
|
||
- 验证JWT签名
|
||
|
||
3. **nginx权限问题**
|
||
- 确保nginx用户有读取权限
|
||
- 检查目录权限设置
|
||
|
||
4. **CORS问题**
|
||
- 检查前端域名配置
|
||
- 验证重定向URI设置
|
||
|
||
## 开发说明
|
||
|
||
### 添加新客户端
|
||
在 `oidc/src/main/java/com/tuoheng/oauth/oidc/config/SecurityConfig.java` 中添加新的 `RegisteredClient`。
|
||
|
||
### 添加新API端点
|
||
在 `resourceservice` 中添加新的Controller和端点。
|
||
|
||
### 修改前端配置
|
||
在 `resourceservicehtml/index.html` 中修改 `oidcConfig` 对象。
|
||
|
||
## 技术栈
|
||
|
||
- **后端**: Spring Boot 3.x, Spring Security, Spring Cloud Gateway
|
||
- **前端**: HTML5, JavaScript, CSS3
|
||
- **认证**: OAuth2, OpenID Connect, JWT
|
||
- **代理**: nginx
|
||
- **构建**: Maven
|
||
|
||
## 版本信息
|
||
|
||
- Spring Boot: 3.5.3
|
||
- Spring Security: 6.5.1
|
||
- Spring Cloud Gateway: 4.1.1
|
||
- Java: 17
|
||
|
||
|
||
mkcert -uninstall && mkcert -install && mkcert -key-file ssl/private.key -cert-file ssl/certificate.crt "*.local.com" local.com |