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

View File

@@ -0,0 +1,119 @@
/**
* JWT 认证守卫
*
* 功能描述:
* - 验证请求中的 JWT 令牌
* - 提取用户信息并添加到请求上下文
* - 保护需要认证的路由
*
* 职责分离:
* - 专注于JWT令牌验证和用户认证
* - 提供统一的认证守卫机制
* - 处理认证失败的异常情况
*
* 最近修改:
* - 2026-01-07: 代码规范优化 - 文件夹扁平化,移除单文件文件夹结构
* - 2026-01-07: 代码规范优化 - 文件重命名为snake_case格式更新注释规范
*
* @author moyin
* @version 1.0.2
* @since 2025-01-05
* @lastModified 2026-01-07
*/
import {
Injectable,
CanActivate,
ExecutionContext,
UnauthorizedException,
Logger,
} from '@nestjs/common';
import { Request } from 'express';
import { LoginCoreService, JwtPayload } from '../../core/login_core/login_core.service';
/**
* 扩展的请求接口,包含用户信息
*/
export interface AuthenticatedRequest extends Request {
user: JwtPayload;
}
@Injectable()
export class JwtAuthGuard implements CanActivate {
private readonly logger = new Logger(JwtAuthGuard.name);
constructor(private readonly loginCoreService: LoginCoreService) {}
/**
* JWT令牌验证和用户认证
*
* 业务逻辑:
* 1. 从请求头中提取Bearer令牌
* 2. 验证令牌的有效性和签名
* 3. 解码令牌获取用户信息
* 4. 将用户信息添加到请求上下文
* 5. 记录认证成功或失败的日志
* 6. 返回认证结果
*
* @param context 执行上下文包含HTTP请求信息
* @returns Promise<boolean> 认证是否成功
* @throws UnauthorizedException 当令牌缺失或无效时
*
* @example
* ```typescript
* @Get('protected')
* @UseGuards(JwtAuthGuard)
* getProtectedData() {
* // 此方法需要有效的JWT令牌才能访问
* }
* ```
*/
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest<Request>();
const token = this.extractTokenFromHeader(request);
if (!token) {
this.logger.warn('访问被拒绝:缺少认证令牌');
throw new UnauthorizedException('缺少认证令牌');
}
try {
// 使用Core层服务验证JWT令牌
const payload = await this.loginCoreService.verifyToken(token, 'access');
// 将用户信息添加到请求对象
(request as AuthenticatedRequest).user = payload;
this.logger.log(`用户认证成功: ${payload.username} (ID: ${payload.sub})`);
return true;
} catch (error) {
const errorMessage = error instanceof Error ? error.message : '未知错误';
this.logger.warn(`JWT 令牌验证失败: ${errorMessage}`);
throw new UnauthorizedException('无效的认证令牌');
}
}
/**
* 从请求头中提取JWT令牌
*
* 业务逻辑:
* 1. 获取Authorization请求头
* 2. 解析Bearer令牌格式
* 3. 验证令牌类型是否为Bearer
* 4. 返回提取的令牌字符串
*
* @param request HTTP请求对象
* @returns string | undefined JWT令牌字符串或undefined
* @throws 无异常抛出返回undefined表示令牌不存在
*
* @example
* ```typescript
* // 请求头格式Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
* const token = this.extractTokenFromHeader(request);
* ```
*/
private extractTokenFromHeader(request: Request): string | undefined {
const [type, token] = request.headers.authorization?.split(' ') ?? [];
return type === 'Bearer' ? token : undefined;
}
}