refactor(auth): 重构认证模块架构 - 将Gateway层组件从Business层分离

范围:src/gateway/auth/, src/business/auth/, src/app.module.ts
涉及文件:
- 新增:src/gateway/auth/ 目录及所有文件
- 移动:Controller、Guard、Decorator、DTO从business层移至gateway层
- 修改:src/business/auth/index.ts(移除Gateway层组件导出)
- 修改:src/app.module.ts(使用AuthGatewayModule替代AuthModule)

主要改进:
- 明确Gateway层和Business层的职责边界
- Controller、Guard、Decorator属于Gateway层职责
- Business层专注于业务逻辑和服务
- 符合分层架构设计原则
This commit is contained in:
moyin
2026-01-14 13:07:11 +08:00
parent f7c3983cc1
commit 73e3e0153c
21 changed files with 565 additions and 220 deletions

338
src/gateway/auth/README.md Normal file
View File

@@ -0,0 +1,338 @@
# 认证网关模块 (Auth Gateway Module)
认证网关模块是系统的HTTP API入口负责处理所有认证相关的HTTP请求包括用户登录、注册、密码管理、邮箱验证等功能提供统一的API接口和完善的安全保护机制。
## 架构层级
**Gateway Layer网关层**
## 职责定位
网关层是系统的HTTP API入口负责
1. **协议处理**处理HTTP请求和响应
2. **数据验证**使用DTO进行请求参数验证
3. **路由管理**定义API端点和路由规则
4. **认证守卫**JWT令牌验证和权限检查
5. **错误转换**将业务错误转换为HTTP状态码
6. **API文档**提供Swagger API文档
## 模块组成
```
src/gateway/auth/
├── login.controller.ts # 登录API控制器
├── login.controller.spec.ts # 登录控制器测试
├── register.controller.ts # 注册API控制器
├── register.controller.spec.ts # 注册控制器测试
├── jwt_auth.guard.ts # JWT认证守卫
├── jwt_auth.guard.spec.ts # JWT认证守卫测试
├── current_user.decorator.ts # 当前用户装饰器
├── jwt_usage_example.ts # JWT使用示例开发参考
├── dto/ # 数据传输对象
│ ├── login.dto.ts # 登录相关DTO
│ └── login_response.dto.ts # 响应DTO
├── auth.gateway.module.ts # 网关模块配置
└── README.md # 模块文档
```
## 依赖关系
```
Gateway Layer (auth.gateway.module)
↓ 依赖
Business Layer (auth.module)
↓ 依赖
Core Layer (login_core.module)
```
## 核心原则
### 1. 只做协议转换,不做业务逻辑
```typescript
// ✅ 正确只做HTTP协议处理
@Post('login')
async login(@Body() loginDto: LoginDto, @Res() res: Response): Promise<void> {
const result = await this.loginService.login({
identifier: loginDto.identifier,
password: loginDto.password
});
this.handleResponse(result, res);
}
// ❌ 错误在Controller中包含业务逻辑
@Post('login')
async login(@Body() loginDto: LoginDto): Promise<any> {
// 验证用户
const user = await this.userService.findByIdentifier(loginDto.identifier);
// 检查密码
const isValid = await this.comparePassword(loginDto.password, user.password);
// ... 更多业务逻辑
}
```
### 2. 统一的错误处理
```typescript
private handleResponse(result: any, res: Response, successStatus: HttpStatus = HttpStatus.OK): void {
if (result.success) {
res.status(successStatus).json(result);
return;
}
const statusCode = this.getErrorStatusCode(result);
res.status(statusCode).json(result);
}
```
### 3. 使用DTO进行数据验证
```typescript
export class LoginDto {
@IsString()
@IsNotEmpty()
identifier: string;
@IsString()
@IsNotEmpty()
password: string;
}
```
## 对外提供的接口
### LoginController
#### login(loginDto: LoginDto, res: Response): Promise<void>
处理用户登录请求,支持用户名、邮箱或手机号多种方式登录。
#### githubOAuth(githubDto: GitHubOAuthDto, res: Response): Promise<void>
处理GitHub OAuth登录请求支持使用GitHub账户登录或注册。
#### refreshToken(refreshTokenDto: RefreshTokenDto, res: Response): Promise<void>
刷新访问令牌,使用有效的刷新令牌生成新的访问令牌。
#### forgotPassword(forgotPasswordDto: ForgotPasswordDto, res: Response): Promise<void>
发送密码重置验证码到用户邮箱或手机。
#### resetPassword(resetPasswordDto: ResetPasswordDto, res: Response): Promise<void>
使用验证码重置用户密码。
#### changePassword(changePasswordDto: ChangePasswordDto, res: Response): Promise<void>
修改用户密码,需要提供旧密码验证。
#### verificationCodeLogin(verificationCodeLoginDto: VerificationCodeLoginDto, res: Response): Promise<void>
使用邮箱或手机号和验证码进行登录,无需密码。
#### sendLoginVerificationCode(sendLoginVerificationCodeDto: SendLoginVerificationCodeDto, res: Response): Promise<void>
向用户邮箱或手机发送登录验证码。
#### debugVerificationCode(sendEmailVerificationDto: SendEmailVerificationDto, res: Response): Promise<void>
获取验证码的详细调试信息,仅用于开发环境。
### RegisterController
#### register(registerDto: RegisterDto, res: Response): Promise<void>
处理用户注册请求,创建新用户账户。
#### sendEmailVerification(sendEmailVerificationDto: SendEmailVerificationDto, res: Response): Promise<void>
向指定邮箱发送验证码。
#### verifyEmail(emailVerificationDto: EmailVerificationDto, res: Response): Promise<void>
使用验证码验证邮箱。
#### resendEmailVerification(sendEmailVerificationDto: SendEmailVerificationDto, res: Response): Promise<void>
重新向指定邮箱发送验证码。
### JwtAuthGuard
#### canActivate(context: ExecutionContext): Promise<boolean>
验证请求中的JWT令牌提取用户信息并添加到请求上下文。
### CurrentUser Decorator
#### CurrentUser(data?: keyof JwtPayload): ParameterDecorator
从请求上下文中提取当前认证用户信息的参数装饰器。
## 对外API接口
### POST /auth/login
用户登录接口支持用户名、邮箱或手机号多种方式登录返回JWT令牌。
### POST /auth/github
GitHub OAuth登录接口使用GitHub账户登录或注册。
### POST /auth/verification-code-login
验证码登录接口,使用邮箱或手机号和验证码进行登录,无需密码。
### POST /auth/refresh-token
刷新访问令牌接口,使用有效的刷新令牌生成新的访问令牌。
### POST /auth/forgot-password
发送密码重置验证码接口,向用户邮箱或手机发送密码重置验证码。
### POST /auth/reset-password
重置密码接口,使用验证码重置用户密码。
### PUT /auth/change-password
修改密码接口,用户修改自己的密码,需要提供旧密码验证。
### POST /auth/send-login-verification-code
发送登录验证码接口,向用户邮箱或手机发送登录验证码。
### POST /auth/debug-verification-code
调试验证码信息接口,获取验证码的详细调试信息,仅用于开发环境。
### POST /auth/register
用户注册接口,创建新用户账户。
### POST /auth/send-email-verification
发送邮箱验证码接口,向指定邮箱发送验证码。
### POST /auth/verify-email
验证邮箱接口,使用验证码验证邮箱。
### POST /auth/resend-email-verification
重新发送邮箱验证码接口,重新向指定邮箱发送验证码。
## 使用的项目内部依赖
### LoginService (来自 business/auth/login.service)
登录业务服务,提供用户登录、密码管理、令牌刷新等业务逻辑。
### RegisterService (来自 business/auth/register.service)
注册业务服务,提供用户注册、邮箱验证等业务逻辑。
### LoginCoreService (来自 core/login_core/login_core.service)
登录核心服务提供JWT令牌验证和生成等技术实现。
### JwtPayload (来自 core/login_core/login_core.service)
JWT令牌载荷类型定义包含用户ID、用户名、角色等信息。
### ThrottlePresets (来自 core/security_core/throttle.decorator)
限流预设配置,提供登录、注册、发送验证码等场景的限流规则。
### TimeoutPresets (来自 core/security_core/timeout.decorator)
超时预设配置,提供不同场景的超时时间设置。
## 核心特性
### 统一的响应处理机制
- 智能错误状态码映射根据错误代码和消息自动选择合适的HTTP状态码
- 统一响应格式所有API返回统一的JSON格式
- 错误信息标准化:提供清晰的错误代码和消息
### 完善的安全保护
- JWT令牌认证使用JWT进行用户身份验证
- 限流保护防止API滥用和暴力破解
- 超时控制:防止长时间阻塞和资源占用
- 请求验证使用DTO和class-validator进行严格的数据验证
### 完整的API文档
- Swagger集成自动生成交互式API文档
- 详细的接口说明每个API都有完整的描述和示例
- 请求响应示例:提供清晰的数据格式说明
### 灵活的认证方式
- 多种登录方式:支持用户名、邮箱、手机号登录
- 验证码登录:支持无密码的验证码登录
- OAuth集成支持GitHub OAuth登录
- 令牌刷新:支持无感知的令牌续期
## 使用示例
### JWT认证完整示例
本模块提供了完整的JWT认证使用示例文件 `jwt_usage_example.ts`,展示了以下场景:
1. **公开接口**:无需认证的接口
2. **受保护接口**需要JWT令牌的接口
3. **用户信息获取**:使用 `@CurrentUser()` 装饰器
4. **特定属性提取**:使用 `@CurrentUser('username')` 获取特定字段
5. **角色权限检查**:基于用户角色的访问控制
详细代码请参考 `src/gateway/auth/jwt_usage_example.ts` 文件。
### 在其他模块中使用认证守卫
```typescript
import { Controller, Get, UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from '../gateway/auth/jwt_auth.guard';
import { CurrentUser } from '../gateway/auth/current_user.decorator';
@Controller('profile')
export class ProfileController {
@Get()
@UseGuards(JwtAuthGuard)
getProfile(@CurrentUser() user: any) {
return { user };
}
}
```
## 与业务层的交互
网关层通过依赖注入使用业务层服务:
```typescript
constructor(
private readonly loginService: LoginService,
private readonly registerService: RegisterService
) {}
```
业务层返回统一的响应格式:
```typescript
interface ApiResponse<T = any> {
success: boolean;
data?: T;
message: string;
error_code?: string;
}
```
## 最佳实践
1. **保持Controller轻量**:只做请求响应处理
2. **使用DTO验证**所有输入都要经过DTO验证
3. **统一错误处理**:使用统一的错误处理方法
4. **完善API文档**使用Swagger装饰器
5. **限流保护**使用Throttle装饰器防止滥用
6. **超时控制**使用Timeout装饰器防止长时间阻塞
## 潜在风险
### 限流配置不当风险
- 限流阈值过低可能影响正常用户使用
- 限流阈值过高无法有效防止攻击
- 缓解措施:根据实际业务场景调整限流参数,监控限流触发情况
### JWT令牌安全风险
- 令牌泄露可能导致账户被盗用
- 令牌过期时间设置不当影响用户体验
- 缓解措施使用HTTPS传输合理设置令牌过期时间实现令牌刷新机制
### 验证码安全风险
- 验证码被暴力破解
- 验证码发送频率过高导致资源浪费
- 缓解措施:限制验证码发送频率,增加验证码复杂度,设置验证码有效期
### API滥用风险
- 恶意用户频繁调用API消耗服务器资源
- 自动化工具批量注册账户
- 缓解措施:实施限流策略,添加人机验证,监控异常请求模式
### 错误信息泄露风险
- 详细的错误信息可能泄露系统实现细节
- 帮助攻击者了解系统弱点
- 缓解措施:生产环境使用通用错误消息,详细日志仅记录在服务器端
## 注意事项
- 网关层不应该直接访问数据库
- 网关层不应该包含复杂的业务逻辑
- 网关层不应该直接调用Core层服务Guard除外
- 所有业务逻辑都应该在Business层实现