# 子系统接入示例

这是一个完整的子系统接入SSO认证中心的示例项目，展示了如何在实际应用中集成OAuth 2.0单点登录。

## 功能特性

- ✅ OAuth 2.0 授权码模式集成
- ✅ 自动跳转SSO登录页
- ✅ 令牌自动管理和刷新
- ✅ 用户信息同步
- ✅ 统一登出
- ✅ 受保护的API接口

## 快速开始

### 1. 配置SSO应用

首先在SSO认证中心创建应用并获取：
- Client ID (应用Key)
- Client Secret (应用密钥)
- 配置回调URL: `http://localhost:8001/auth/callback`

### 2. 启动后端

```bash
cd backend

# 安装依赖
pip install -r requirements.txt

# 配置环境变量
cp .env.example .env
# 编辑 .env 文件，填入SSO应用的配置信息

# 启动服务
python main.py
```

后端服务运行在 `http://localhost:8001`

### 3. 启动前端

```bash
cd frontend

# 安装依赖
npm install

# 启动开发服务器
npm run dev
```

前端服务运行在 `http://localhost:3001`

## 使用流程

1. 访问 `http://localhost:3001`
2. 点击登录按钮
3. 自动跳转到SSO登录页 (`http://localhost:8000/oauth/authorize`)
4. 输入用户名和密码登录
5. 授权后自动跳转回子系统
6. 子系统获取用户信息并建立会话

## 技术实现

### 后端实现要点

1. **发起授权请求**
```python
@app.get("/auth/login")
async def login():
    params = {
        "response_type": "code",
        "client_id": CLIENT_ID,
        "redirect_uri": REDIRECT_URI,
        "scope": "profile email",
        "state": generate_state()
    }
    auth_url = f"{SSO_BASE_URL}/oauth/authorize?{urlencode(params)}"
    return RedirectResponse(url=auth_url)
```

2. **处理授权回调**
```python
@app.get("/auth/callback")
async def auth_callback(code: str):
    # 用授权码换取访问令牌
    token_response = await exchange_code_for_token(code)
    
    # 获取用户信息
    user_info = await get_user_info(token_response.access_token)
    
    # 建立本地会话
    create_session(user_info, token_response)
    
    return redirect_to_frontend()
```

3. **保护API接口**
```python
async def get_current_user(credentials = Depends(security)):
    token = credentials.credentials
    
    # 验证token
    user_info = await verify_token_with_sso(token)
    
    return user_info

@app.get("/api/protected")
async def protected_route(user = Depends(get_current_user)):
    return {"data": "protected data"}
```

### 前端实现要点

1. **登录跳转**
```typescript
function login() {
  window.location.href = 'http://localhost:8001/auth/login'
}
```

2. **处理回调**
```typescript
// 在回调页面获取token
const urlParams = new URLSearchParams(window.location.search)
const token = urlParams.get('token')

if (token) {
  // 保存token
  localStorage.setItem('access_token', token)
  
  // 跳转到首页
  router.push('/dashboard')
}
```

3. **API请求拦截**
```typescript
axios.interceptors.request.use(config => {
  const token = localStorage.getItem('access_token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})
```

## API接口

### 认证相关

- `GET /auth/login` - 发起SSO登录
- `GET /auth/callback` - 处理SSO回调
- `GET /auth/logout` - 用户登出

### 业务接口（需要认证）

- `GET /api/user/profile` - 获取用户资料
- `GET /api/products` - 获取产品列表
- `GET /api/orders` - 获取订单列表

## 注意事项

1. **安全性**
   - 生产环境必须使用HTTPS
   - 妥善保管Client Secret
   - 验证state参数防止CSRF攻击
   - 定期刷新访问令牌

2. **错误处理**
   - 处理授权失败情况
   - 处理令牌过期情况
   - 处理网络错误

3. **用户体验**
   - 保存用户登录状态
   - 自动刷新令牌
   - 提供友好的错误提示

## 扩展功能

可以根据实际需求添加：

- 用户信息本地缓存
- 令牌自动刷新机制
- 多租户支持
- 权限验证
- 审计日志

## 故障排查

### 常见问题

1. **授权失败**
   - 检查Client ID和Secret是否正确
   - 检查回调URL是否匹配
   - 检查SSO服务是否正常运行

2. **令牌验证失败**
   - 检查令牌是否过期
   - 检查令牌格式是否正确
   - 检查SSO服务连接是否正常

3. **跨域问题**
   - 检查CORS配置
   - 检查代理配置

## 参考资料

- [OAuth 2.0 RFC 6749](https://tools.ietf.org/html/rfc6749)
- [JWT RFC 7519](https://tools.ietf.org/html/rfc7519)
- [FastAPI文档](https://fastapi.tiangolo.com/)
- [Vue 3文档](https://vuejs.org/)