全网最硬核NestJS实战手册(二):请求管线、数据持久化与认证授权全解析
全网最硬核NestJS实战手册二请求管线、数据持久化与认证授权全解析前置阅读[一从零搭建你的第一个企业级Node.js后端项目] 本文假定读者已掌握 Controller、Provider/DI、Module 三大基础概念。一、请求管线全景图NestJS 的请求处理是一个多阶段的管线。理解每个阶段的职责和执行顺序是写出健壮后端代码的关键Request → Middleware中间件 → Guard守卫 → Interceptor拦截器 - before → Pipe管道 → Controller控制器方法 → Interceptor拦截器 - after → Exception Filter异常过滤器 → Response下面按执行顺序逐一拆解。二、Middleware请求的第一道关卡中间件是在路由处理器之前执行的函数可访问请求对象Request、响应对象Response和next()函数。适用于请求日志、CORS 头设置、请求体解析等场景。自定义日志中间件import { Injectable, NestMiddleware } from nestjs/common; import { Request, Response, NextFunction } from express; Injectable() export class LoggerMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { console.log([${new Date().toISOString()}] ${req.method} ${req.path}); next(); } }在模块中配置中间件支持精确的路径匹配和排除规则export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer .apply(LoggerMiddleware) .exclude( { path: cats, method: RequestMethod.GET }, { path: health, method: RequestMethod.ALL } ) .forRoutes(CatsController); } }forRoutes可以传入控制器类、路由路径字符串或通配符*。三、Guard权限的守门人Guard 实现了CanActivate接口用于权限校验和身份验证。它在所有中间件之后、拦截器和管道之前执行。返回true则放行返回false则拒绝请求返回 403 Forbidden。角色守卫实现import { Injectable, CanActivate, ExecutionContext } from nestjs/common; Injectable() export class RolesGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request context.switchToHttp().getRequest(); const user request.user; return user user.roles user.roles.includes(admin); } }绑定方式Guard 支持控制器级别、方法级别和全局级别三种绑定方式// 控制器级别 Controller(cats) UseGuards(RolesGuard) export class CatsController {} // 方法级别 Get() UseGuards(RolesGuard) findAll() {} // 全局级别 (main.ts) const app await NestFactory.create(AppModule); app.useGlobalGuards(new RolesGuard());四、Interceptor数据的拦截器Interceptor 实现了NestInterceptor接口基于 RxJS 的Observable可以在方法执行前后拦截和变换数据流。典型场景包括响应格式统一包装、执行时间记录、缓存处理等。响应统一包装import { Injectable, NestInterceptor, ExecutionContext, CallHandler, } from nestjs/common; import { Observable } from rxjs; import { map } from rxjs/operators; export interface ResponseT { data: T; success: boolean; } Injectable() export class TransformInterceptorT implements NestInterceptorT, ResponseT { intercept( context: ExecutionContext, next: CallHandler, ): ObservableResponseT { return next.handle().pipe(map(data ({ data, success: true }))); } }执行时间记录Injectable() export class LoggingInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observableany { const now Date.now(); return next .handle() .pipe(tap(() console.log(Duration: ${Date.now() - now}ms))); } }next.handle()返回的是 Observablepipe()中的操作符在响应返回时执行after 阶段。在next.handle()之前的代码属于 before 阶段。五、Pipe数据的守门人Pipe 实现了PipeTransform接口承担两大职责数据转换如字符串转数字和输入验证校验数据格式。管道在控制器方法调用之前执行如果验证失败则抛出异常阻止方法执行。内置管道NestJS 提供 10 个开箱即用的内置管道ValidationPipe、ParseIntPipe、ParseFloatPipe、ParseBoolPipe、ParseArrayPipe、ParseUUIDPipe、ParseEnumPipe、DefaultValuePipe、ParseFilePipe、ParseDatePipe参数级绑定Get(:id) findOne(Param(id, ParseIntPipe) id: number) { return this.catsService.findOne(id); }当访问/cats/abc时ParseIntPipe会抛出 400 异常{ statusCode: 400, message: Validation failed (numeric string is expected), error: Bad Request }自定义管道import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException, } from nestjs/common; Injectable() export class ParsePositiveIntPipe implements PipeTransformstring, number { transform(value: string, metadata: ArgumentMetadata): number { const val parseInt(value, 10); if (isNaN(val) || val 0) { throw new BadRequestException(ID must be a positive integer); } return val; } }六、Exception Filter异常的终结者NestJS 内置全局异常层自动捕获所有未处理的异常并返回统一的 JSON 响应。当业务需要自定义错误格式或处理特定异常类型时可使用自定义异常过滤器。自定义异常类import { HttpException, HttpStatus } from nestjs/common; export class ForbiddenException extends HttpException { constructor() { super(Forbidden, HttpStatus.FORBIDDEN); } }自定义异常过滤器import { ExceptionFilter, Catch, ArgumentsHost, HttpException, } from nestjs/common; import { Response } from express; Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx host.switchToHttp(); const response ctx.getResponseResponse(); const status exception.getStatus(); response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), path: ctx.getRequest().url, }); } }Catch()可以传入多个异常类型不传参数则捕获所有异常。七、数据持久化TypeORM 与 PrismaTypeORM 集成TypeORM 是与 NestJS 配合最紧密的 ORM 框架npm install --save nestjs/typeorm typeorm mysql2Module({ imports: [ TypeOrmModule.forRoot({ type: mysql, host: localhost, port: 3306, username: root, password: password, database: nest_demo, entities: [Cat], synchronize: true, // 生产环境必须关闭 }), ], }) export class AppModule {}实体定义import { Entity, Column, PrimaryGeneratedColumn } from typeorm; Entity() export class Cat { PrimaryGeneratedColumn() id: number; Column() name: string; Column() age: number; Column() breed: string; }Repository 模式Injectable() export class CatsService { constructor( InjectRepository(Cat) private catsRepository: RepositoryCat, ) {} findAll(): PromiseCat[] { return this.catsRepository.find(); } findOne(id: number): PromiseCat | null { return this.catsRepository.findOneBy({ id }); } async create(cat: CreateCatDto): PromiseCat { return this.catsRepository.save(cat); } async remove(id: number): Promisevoid { await this.catsRepository.delete(id); } }Prisma 集成Prisma 是新一代 ORM提供类型安全的数据库客户端npm install prisma --save-dev npm install prisma/client npx prisma init// prisma.service.ts import { Injectable, OnModuleInit, OnModuleDestroy } from nestjs/common; import { PrismaClient } from prisma/client; Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { async onModuleInit() { await this.$connect(); } async onModuleDestroy() { await this.$disconnect(); } }通过extends PrismaClient将 Prisma 客户端封装为 NestJS Provider利用OnModuleInit和OnModuleDestroy生命周期钩子管理连接。八、请求验证DTO class-validatorDTO 定义与验证规则NestJS 推荐使用 DTOData Transfer Object定义数据传输格式配合class-validator实现声明式验证npm install class-validator class-transformerimport { IsString, IsInt, Min, Max, IsNotEmpty } from class-validator; export class CreateCatDto { IsString() IsNotEmpty() name: string; IsInt() Min(0) Max(30) age: number; IsString() IsNotEmpty() breed: string; }全局启用 ValidationPipeimport { ValidationPipe } from nestjs/common; async function bootstrap() { const app await NestFactory.create(AppModule); app.useGlobalPipes( new ValidationPipe({ whitelist: true, // 自动剥离非白名单属性 forbidNonWhitelisted: true, // 存在非白名单属性时抛出异常 transform: true, // 自动类型转换 }), ); await app.listen(3000); }三个关键配置whitelist: true自动删除 DTO 中未定义的属性防止恶意字段注入forbidNonWhitelisted: true检测到未定义属性时直接抛出 400 错误而非静默删除transform: true将请求中的字符串自动转换为 DTO 声明的类型如字符串5→ 数字5九、认证与授权JWT RBACJWT 认证npm install nestjs/jwt nestjs/passport passport passport-jwtJWT 模块配置Module({ imports: [ JwtModule.register({ secret: your-secret-key, signOptions: { expiresIn: 1h }, }), ], providers: [AuthService], exports: [AuthService], }) export class AuthModule {}JWT 策略Passport 集成import { Injectable } from nestjs/common; import { PassportStrategy } from nestjs/passport; import { ExtractJwt, Strategy } from passport-jwt; Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor() { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, secretOrKey: your-secret-key, }); } async validate(payload: any) { return { userId: payload.sub, username: payload.username }; } }保护路由Controller(profile) export class ProfileController { UseGuards(AuthGuard(jwt)) Get() getProfile() { return { message: This is a protected route }; } }RBAC 角色控制结合自定义装饰器和 Guard 实现基于角色的访问控制// roles.decorator.ts import { SetMetadata } from nestjs/common; export const Roles (...roles: string[]) SetMetadata(roles, roles);Controller(admin) UseGuards(JwtAuthGuard, RolesGuard) export class AdminController { Roles(admin) Get() adminOnly() { return { message: Admin content }; } Roles(user, admin) Get(dashboard) dashboard() { return { message: Dashboard content }; } }SetMetadata将角色信息附着在路由处理器上RolesGuard通过Reflector读取元数据并与当前用户角色比对。十、小结与下一步本篇覆盖了 NestJS 请求管线中的五大组件以及数据持久化和认证授权的完整实现组件职责典型场景Middleware请求预处理日志、CORS、压缩Guard权限校验认证、角色检查Interceptor数据拦截变换响应包装、性能监控Pipe转换与验证参数校验、类型转换Exception Filter异常处理统一错误格式、异常分类下一篇将进入精通阶段GraphQL 集成、WebSocket 实时通信、微服务架构、任务调度、文件上传、测试策略、生产部署优化与最佳实践。幸得你于纷扰时光里驻足品读由衷致谢Thank you for watching in your busy schedule. Thank you.