NestJS问题:排除/api/docs路由后仍无法绕过Basic Auth中间件
解决NestJS Basic Auth中间件无法排除Swagger路由的问题
问题根源
- Swagger路由不止一个:除了
/api/docs,Swagger UI还会请求/swagger-ui.html、/api-json等静态资源路由,仅排除单个路径会导致这些资源被拦截 - 中间件异常返回错误:当前中间件直接
return new UnauthorizedException(),这种方式在Express中间件中无法被Nest的异常处理器正确处理 - 路径匹配精度不足:字符串路径的精确匹配无法覆盖带查询参数的请求(如
/api/docs?foo=bar)
修复步骤
1. 修正中间件的异常处理逻辑
将直接返回异常改为抛出异常,确保Nest能正确处理认证失败场景:
import type { NestMiddleware } from '@nestjs/common'; import { Injectable, UnauthorizedException } from '@nestjs/common'; import type { NextFunction, Request, Response } from 'express'; import { ApiConfigService } from '@shared/config.service'; @Injectable() export class BasicAuthMiddleware implements NestMiddleware { constructor(private configService: ApiConfigService) {} use(req: Request, res: Response, next: NextFunction) { if (req.headers['authorization']) { const authorization = req.headers['authorization']; const basic = authorization.match(/^Basic (.+)$/); if (!basic) { throw new UnauthorizedException(); } const credentials = Buffer.from(basic[1], 'base64').toString('utf-8'); const { username, password } = this.configService.basicAuthConfig; if (credentials !== `${username}:${password}`) { throw new UnauthorizedException(); } return next(); } throw new UnauthorizedException(); } }
2. 扩展排除的Swagger相关路由
使用正则表达式匹配所有Swagger相关路径,确保覆盖所有静态资源:
import { Module, NestModule, RequestMethod, MiddlewareConsumer } from '@nestjs/common'; // 其他导入... export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer .apply(BasicAuthMiddleware) .exclude( /^\/api\/docs(\/.*)?$/, /^\/swagger-ui(\/.*)?$/, /^\/api(-json)?$/ ) .forRoutes({ path: '*', method: RequestMethod.ALL }); } }
3. (可选)使用路径对象精确匹配
若不想用正则,可配置多个路径对象实现精确排除:
export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer .apply(BasicAuthMiddleware) .exclude( { path: '/api/docs', method: RequestMethod.GET }, { path: '/swagger-ui', method: RequestMethod.GET }, { path: '/swagger-ui/*', method: RequestMethod.GET }, { path: '/api-json', method: RequestMethod.GET } ) .forRoutes({ path: '*', method: RequestMethod.ALL }); } }
验证方式
启动服务后,直接访问/api/docs应能正常加载Swagger UI且无需凭证;访问其他业务路由(如/api/users)则会触发Basic Auth验证。
内容的提问来源于stack exchange,提问作者dokichan
相关产品推荐
相关产品推荐

