392 lines
8.6 KiB
Markdown
392 lines
8.6 KiB
Markdown
# 部署和集成指南
|
||
|
||
本文档说明如何将新的安全功能集成到现有系统中。
|
||
|
||
## 📦 已完成的功能
|
||
|
||
### 1. 数据加密模块
|
||
- ✅ `app/core/encryption.py` - Fernet 对称加密实现
|
||
- ✅ 支持敏感数据加密/解密
|
||
- ✅ 密钥管理和生成工具
|
||
|
||
### 2. 用户认证系统
|
||
- ✅ `app/domain/models/role.py` - 用户角色枚举 (ADMIN/OPERATOR/USER/VIEWER)
|
||
- ✅ `app/domain/schemas/user.py` - 用户数据模型和验证
|
||
- ✅ `app/infra/repositories/user_repository.py` - 用户数据访问层
|
||
- ✅ `app/api/v1/endpoints/auth.py` - 注册/登录/刷新Token接口
|
||
- ✅ `app/auth/dependencies.py` - 认证依赖项
|
||
- ✅ `migrations/001_create_users_table.sql` - 用户表迁移脚本
|
||
|
||
### 3. 权限控制系统
|
||
- ✅ `app/auth/permissions.py` - RBAC 权限控制装饰器
|
||
- ✅ `app/api/v1/endpoints/user_management.py` - 用户管理接口示例
|
||
- ✅ 支持基于角色的访问控制
|
||
- ✅ 支持资源所有者检查
|
||
|
||
### 4. 审计日志系统
|
||
- ✅ `app/core/audit.py` - 审计日志核心功能
|
||
- ✅ `app/domain/schemas/audit.py` - 审计日志数据模型
|
||
- ✅ `app/infra/repositories/audit_repository.py` - 审计日志数据访问层
|
||
- ✅ `app/api/v1/endpoints/audit.py` - 审计日志查询接口
|
||
- ✅ `app/infra/audit/middleware.py` - 自动审计中间件
|
||
- ✅ `migrations/002_create_audit_logs_table.sql` - 审计日志表迁移脚本
|
||
|
||
### 5. 文档和测试
|
||
- ✅ `SECURITY_README.md` - 完整的使用文档
|
||
- ✅ `.env.example` - 环境变量配置模板
|
||
- ✅ `tests/test_encryption.py` - 加密功能测试
|
||
|
||
---
|
||
|
||
## 🔧 集成步骤
|
||
|
||
### 步骤 1: 环境配置
|
||
|
||
1. 复制环境变量模板:
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
2. 生成密钥并填写 `.env`:
|
||
```bash
|
||
# JWT 密钥
|
||
openssl rand -hex 32
|
||
|
||
# 加密密钥
|
||
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||
```
|
||
|
||
3. 编辑 `.env` 填写所有必需的配置项。
|
||
|
||
### 步骤 2: 数据库迁移
|
||
|
||
执行数据库迁移脚本:
|
||
|
||
```bash
|
||
# 方法 1: 使用 psql 命令
|
||
psql -U postgres -d tjwater -f migrations/001_create_users_table.sql
|
||
psql -U postgres -d tjwater -f migrations/002_create_audit_logs_table.sql
|
||
|
||
# 方法 2: 在 psql 交互界面
|
||
psql -U postgres -d tjwater
|
||
\i migrations/001_create_users_table.sql
|
||
\i migrations/002_create_audit_logs_table.sql
|
||
```
|
||
|
||
验证表已创建:
|
||
|
||
```sql
|
||
-- 检查用户表
|
||
SELECT * FROM users;
|
||
|
||
-- 检查审计日志表
|
||
SELECT * FROM audit_logs;
|
||
```
|
||
|
||
### 步骤 3: 更新 main.py
|
||
|
||
在 `app/main.py` 中集成新功能:
|
||
|
||
```python
|
||
from fastapi import FastAPI
|
||
from app.core.config import settings
|
||
from app.infra.audit.middleware import AuditMiddleware
|
||
|
||
app = FastAPI(title=settings.PROJECT_NAME)
|
||
|
||
# 1. 添加审计中间件(可选)
|
||
app.add_middleware(AuditMiddleware)
|
||
|
||
# 2. 注册路由
|
||
from app.api.v1.endpoints import auth, user_management, audit
|
||
|
||
app.include_router(
|
||
auth.router,
|
||
prefix=f"{settings.API_V1_STR}/auth",
|
||
tags=["认证"]
|
||
)
|
||
|
||
app.include_router(
|
||
user_management.router,
|
||
prefix=f"{settings.API_V1_STR}/users",
|
||
tags=["用户管理"]
|
||
)
|
||
|
||
app.include_router(
|
||
audit.router,
|
||
prefix=f"{settings.API_V1_STR}/audit",
|
||
tags=["审计日志"]
|
||
)
|
||
|
||
# 3. 确保数据库在启动时初始化
|
||
@app.on_event("startup")
|
||
async def startup_event():
|
||
# 初始化数据库连接池
|
||
from app.infra.db.postgresql.database import Database
|
||
global db
|
||
db = Database()
|
||
db.init_pool()
|
||
await db.open()
|
||
|
||
@app.on_event("shutdown")
|
||
async def shutdown_event():
|
||
# 关闭数据库连接
|
||
await db.close()
|
||
```
|
||
|
||
### 步骤 4: 保护现有接口
|
||
|
||
#### 方法 1: 为路由添加全局依赖
|
||
|
||
```python
|
||
from app.auth.dependencies import get_current_active_user
|
||
|
||
# 为整个路由器添加认证
|
||
router = APIRouter(dependencies=[Depends(get_current_active_user)])
|
||
```
|
||
|
||
#### 方法 2: 为单个端点添加依赖
|
||
|
||
```python
|
||
from app.auth.permissions import require_role, get_current_admin
|
||
from app.domain.models.role import UserRole
|
||
|
||
@router.get("/data")
|
||
async def get_data(
|
||
current_user = Depends(require_role(UserRole.USER))
|
||
):
|
||
"""需要 USER 及以上角色"""
|
||
return {"data": "protected"}
|
||
|
||
@router.delete("/data/{id}")
|
||
async def delete_data(
|
||
id: int,
|
||
current_user = Depends(get_current_admin)
|
||
):
|
||
"""仅管理员可访问"""
|
||
return {"message": "deleted"}
|
||
```
|
||
|
||
### 步骤 5: 添加审计日志
|
||
|
||
#### 自动审计(推荐)
|
||
|
||
使用中间件自动记录(已在 main.py 中添加):
|
||
|
||
```python
|
||
app.add_middleware(AuditMiddleware)
|
||
```
|
||
|
||
#### 手动审计
|
||
|
||
在关键业务逻辑中手动记录:
|
||
|
||
```python
|
||
from app.core.audit import log_audit_event, AuditAction
|
||
|
||
@router.post("/important-action")
|
||
async def important_action(
|
||
data: dict,
|
||
request: Request,
|
||
current_user = Depends(get_current_active_user)
|
||
):
|
||
# 执行业务逻辑
|
||
result = do_something(data)
|
||
|
||
# 记录审计日志
|
||
await log_audit_event(
|
||
action=AuditAction.UPDATE,
|
||
user_id=current_user.id,
|
||
username=current_user.username,
|
||
resource_type="important_resource",
|
||
resource_id=str(result.id),
|
||
ip_address=request.client.host,
|
||
request_data=data
|
||
)
|
||
|
||
return result
|
||
```
|
||
|
||
### 步骤 6: 更新 auth/dependencies.py
|
||
|
||
确保 `get_db()` 函数正确获取数据库实例:
|
||
|
||
```python
|
||
async def get_db() -> Database:
|
||
"""获取数据库实例"""
|
||
# 方法 1: 从 main.py 导入
|
||
from app.main import db
|
||
return db
|
||
|
||
# 方法 2: 从 FastAPI app.state 获取
|
||
# from fastapi import Request
|
||
# def get_db_from_request(request: Request):
|
||
# return request.app.state.db
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 测试
|
||
|
||
### 1. 测试加密功能
|
||
|
||
```bash
|
||
python tests/test_encryption.py
|
||
```
|
||
|
||
### 2. 测试 API
|
||
|
||
启动服务器:
|
||
|
||
```bash
|
||
uvicorn app.main:app --reload
|
||
```
|
||
|
||
访问交互式文档:
|
||
- Swagger UI: http://localhost:8000/docs
|
||
- ReDoc: http://localhost:8000/redoc
|
||
|
||
### 3. 测试登录
|
||
|
||
```bash
|
||
curl -X POST "http://localhost:8000/api/v1/auth/login" \
|
||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||
-d "username=admin&password=admin123"
|
||
```
|
||
|
||
### 4. 测试受保护接口
|
||
|
||
```bash
|
||
TOKEN="your-access-token"
|
||
curl -X GET "http://localhost:8000/api/v1/auth/me" \
|
||
-H "Authorization: Bearer $TOKEN"
|
||
```
|
||
|
||
---
|
||
|
||
## 🔄 迁移现有接口
|
||
|
||
### 原有硬编码认证
|
||
|
||
**旧代码** (`app/api/v1/endpoints/auth.py`):
|
||
```python
|
||
AUTH_TOKEN = "567e33c876a2"
|
||
|
||
async def verify_token(authorization: str = Header()):
|
||
token = authorization.split(" ")[1]
|
||
if token != AUTH_TOKEN:
|
||
raise HTTPException(status_code=403)
|
||
```
|
||
|
||
**新代码** (已更新):
|
||
```python
|
||
from app.auth.dependencies import get_current_active_user
|
||
|
||
@router.get("/protected")
|
||
async def protected_route(
|
||
current_user = Depends(get_current_active_user)
|
||
):
|
||
return {"user": current_user.username}
|
||
```
|
||
|
||
### 更新其他端点
|
||
|
||
搜索项目中使用旧认证的地方:
|
||
|
||
```bash
|
||
grep -r "AUTH_TOKEN" app/
|
||
grep -r "verify_token" app/
|
||
```
|
||
|
||
替换为新的依赖注入系统。
|
||
|
||
---
|
||
|
||
## 📋 检查清单
|
||
|
||
部署前检查:
|
||
|
||
- [ ] 环境变量已配置(`.env`)
|
||
- [ ] 数据库迁移已执行
|
||
- [ ] 默认管理员账号可登录
|
||
- [ ] JWT Token 可正常生成和验证
|
||
- [ ] 权限控制正常工作
|
||
- [ ] 审计日志正常记录
|
||
- [ ] 加密功能测试通过
|
||
- [ ] API 文档可访问
|
||
|
||
---
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
### 1. 向后兼容性
|
||
|
||
保留了简化版登录接口 `/auth/login/simple` 以兼容旧客户端:
|
||
|
||
```python
|
||
@router.post("/login/simple")
|
||
async def login_simple(username: str, password: str):
|
||
# 验证并返回 Token
|
||
...
|
||
```
|
||
|
||
### 2. 数据库连接
|
||
|
||
确保在 `app/auth/dependencies.py` 中 `get_db()` 函数能正确获取数据库实例。
|
||
|
||
### 3. 密钥安全
|
||
|
||
- ❌ 不要提交 `.env` 文件到版本控制
|
||
- ✅ 在生产环境使用环境变量或密钥管理服务
|
||
- ✅ 定期轮换 JWT 密钥
|
||
|
||
### 4. 性能考虑
|
||
|
||
- 审计中间件会增加每个请求的处理时间(约 5-10ms)
|
||
- 对高频接口可考虑异步记录审计日志
|
||
- 定期清理或归档旧的审计日志
|
||
|
||
---
|
||
|
||
## 🐛 故障排查
|
||
|
||
### 问题 1: 导入错误
|
||
|
||
```
|
||
ImportError: cannot import name 'db' from 'app.main'
|
||
```
|
||
|
||
**解决**: 确保在 `app/main.py` 中定义了全局 `db` 对象。
|
||
|
||
### 问题 2: 认证失败
|
||
|
||
```
|
||
401 Unauthorized: Could not validate credentials
|
||
```
|
||
|
||
**检查**:
|
||
1. Token 是否正确设置在 `Authorization: Bearer {token}` header
|
||
2. Token 是否过期
|
||
3. SECRET_KEY 是否配置正确
|
||
|
||
### 问题 3: 数据库连接失败
|
||
|
||
```
|
||
psycopg.OperationalError: connection failed
|
||
```
|
||
|
||
**检查**:
|
||
1. PostgreSQL 是否运行
|
||
2. `.env` 中数据库配置是否正确
|
||
3. 数据库是否存在
|
||
|
||
---
|
||
|
||
## 📞 技术支持
|
||
|
||
详细文档请参考:
|
||
- `SECURITY_README.md` - 安全功能使用指南
|
||
- `migrations/` - 数据库迁移脚本
|
||
- `app/domain/schemas/` - 数据模型定义
|
||
|