# NestJS 认证处理指南 ## 认证架构对比 ### 1. PHP ThinkPHP (传统方式) ```php // 通过中间件全局处理 class AdminCheckToken { public function handle(Request $request, Closure $next) { // 检查token,某些路由可以跳过 } } ``` ### 2. Java Spring Boot (注解方式) ```java @RestController public class AuthController { @SaCheckLogin // 需要登录 @GetMapping("/user/info") public UserInfo getUserInfo() {} @SaNotCheckLogin // 免登录 @PostMapping("/login") public LoginResult login() {} } ``` ### 3. NestJS (装饰器方式) - 更像Java ```typescript @Controller('adminapi/auth') export class AuthController { @Public() // 免登录 @Post('login') async login() {} @Get('user/info') // 需要登录(默认) async getUserInfo() {} } ``` ## NestJS 认证处理方式 ### 核心原则 1. **默认需要登录** - 所有接口默认需要认证 2. **@Public()装饰器** - 标记免登录接口 3. **全局守卫** - 统一处理认证逻辑 ### 实现方式 #### 1. 全局守卫配置 ```typescript // app.module.ts @Module({ providers: [ { provide: APP_GUARD, useClass: GlobalAuthGuard }, ], }) export class AppModule {} ``` #### 2. 全局守卫实现 ```typescript // GlobalAuthGuard.ts @Injectable() export class GlobalAuthGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { // 检查是否有 @Public() 装饰器 const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ context.getHandler(), context.getClass(), ]); if (isPublic) { return true; // 免登录接口直接通过 } // 需要认证的接口使用JWT认证 return this.jwtAuthGuard.canActivate(context); } } ``` #### 3. 免登录装饰器 ```typescript // public.decorator.ts export const IS_PUBLIC_KEY = 'isPublic'; export const Public = () => SetMetadata(IS_PUBLIC_KEY, true); ``` ### 接口分类 #### 1. 免登录接口 (使用 @Public()) - **登录相关**: `/adminapi/login/*` - **验证码相关**: `/adminapi/captcha/*` - **公开配置**: `/api/sys/*` (前台公开接口) - **管理端公开**: `/adminapi/sys/web/*` (管理端公开接口) #### 2. 需要登录接口 (默认) - **用户管理**: `/adminapi/auth/*` - **系统管理**: `/adminapi/sys/*` (除公开接口外) - **站点管理**: `/adminapi/site/*` - **其他业务接口**: 所有其他接口 ### 路由路径对齐 #### PHP → NestJS 路径映射 ```typescript // PHP: /adminapi/sys/get/website // NestJS: @Get('get/website') 在 @Controller('adminapi/sys') // PHP: /adminapi/login // NestJS: @Get('login') 在 @Controller('adminapi') + @Public() // PHP: /adminapi/captcha/create // NestJS: @Get('create') 在 @Controller('adminapi/captcha') + @Public() ``` ### 最佳实践 #### 1. 控制器级别设置 ```typescript // 免登录控制器 @Controller('adminapi/login') @Public() // 整个控制器免登录 export class LoginController {} // 需要登录控制器 @Controller('adminapi/sys') @UseGuards(JwtAuthGuard, RolesGuard) // 整个控制器需要登录 export class ConfigController {} ``` #### 2. 方法级别设置 ```typescript @Controller('adminapi/sys') export class ConfigController { @Public() // 单个方法免登录 @Get('web/website') async getWebWebsite() {} @Get('get/website') // 默认需要登录 async getWebsite() {} } ``` #### 3. 路径命名规范 - **PHP方法名**: `getWebsite()` → **NestJS路径**: `get/website` - **PHP方法名**: `setWebsite()` → **NestJS路径**: `set/website` - **PHP方法名**: `getSceneDomain()` → **NestJS路径**: `get/scene/domain` ### 验证方法 #### 1. 检查免登录接口 ```bash # 这些接口应该不需要token就能访问 curl http://localhost:3001/adminapi/login curl http://localhost:3001/adminapi/captcha/create curl http://localhost:3001/api/sys/website ``` #### 2. 检查需要登录接口 ```bash # 这些接口需要token才能访问 curl -H "Authorization: Bearer " http://localhost:3001/adminapi/sys/get/website curl -H "Authorization: Bearer " http://localhost:3001/adminapi/site/lists ``` ### 总结 NestJS的认证处理方式**更像Java Spring Boot**,使用装饰器模式: 1. **@Public()** = Java的 **@SaNotCheckLogin** 2. **默认需要登录** = Java的 **@SaCheckLogin** 3. **全局守卫** = Java的 **拦截器** 这种方式比PHP的中间件方式更加灵活和类型安全,符合现代框架的设计理念。