- 新增JWT认证守卫(JwtAuthGuard)和当前用户装饰器(CurrentUser) - 添加JWT使用示例和完整的认证流程文档 - 实现Zulip用户管理服务,支持用户查询、验证和管理 - 实现Zulip用户注册服务,支持新用户创建和注册流程 - 添加完整的单元测试覆盖 - 新增真实环境测试脚本,验证Zulip API集成 - 更新.gitignore,排除.kiro目录 主要功能: - JWT令牌验证和用户信息提取 - 用户存在性检查和信息获取 - Zulip API集成和错误处理 - 完整的测试覆盖和文档
83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
/**
|
|
* JWT 认证守卫
|
|
*
|
|
* 功能描述:
|
|
* - 验证请求中的 JWT 令牌
|
|
* - 提取用户信息并添加到请求上下文
|
|
* - 保护需要认证的路由
|
|
*
|
|
* @author kiro-ai
|
|
* @version 1.0.0
|
|
* @since 2025-01-05
|
|
*/
|
|
|
|
import {
|
|
Injectable,
|
|
CanActivate,
|
|
ExecutionContext,
|
|
UnauthorizedException,
|
|
Logger,
|
|
} from '@nestjs/common';
|
|
import { JwtService } from '@nestjs/jwt';
|
|
import { Request } from 'express';
|
|
|
|
/**
|
|
* JWT 载荷接口
|
|
*/
|
|
export interface JwtPayload {
|
|
sub: string; // 用户ID
|
|
username: string;
|
|
role: number;
|
|
iat: number; // 签发时间
|
|
exp: number; // 过期时间
|
|
}
|
|
|
|
/**
|
|
* 扩展的请求接口,包含用户信息
|
|
*/
|
|
export interface AuthenticatedRequest extends Request {
|
|
user: JwtPayload;
|
|
}
|
|
|
|
@Injectable()
|
|
export class JwtAuthGuard implements CanActivate {
|
|
private readonly logger = new Logger(JwtAuthGuard.name);
|
|
|
|
constructor(private readonly jwtService: JwtService) {}
|
|
|
|
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 {
|
|
// 验证并解码 JWT 令牌
|
|
const payload = await this.jwtService.verifyAsync<JwtPayload>(token);
|
|
|
|
// 将用户信息添加到请求对象
|
|
(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 令牌
|
|
*
|
|
* @param request 请求对象
|
|
* @returns JWT 令牌或 undefined
|
|
*/
|
|
private extractTokenFromHeader(request: Request): string | undefined {
|
|
const [type, token] = request.headers.authorization?.split(' ') ?? [];
|
|
return type === 'Bearer' ? token : undefined;
|
|
}
|
|
} |