2025-09-21 21:29:28 +08:00
|
|
|
# NestJS 认证处理指南
|
|
|
|
|
|
|
|
|
|
## 认证架构对比
|
|
|
|
|
|
2025-10-26 20:40:23 +08:00
|
|
|
### 1. Java Spring Boot (注解方式)
|
2025-09-21 21:29:28 +08:00
|
|
|
```java
|
|
|
|
|
@RestController
|
|
|
|
|
public class AuthController {
|
|
|
|
|
@SaCheckLogin // 需要登录
|
|
|
|
|
@GetMapping("/user/info")
|
|
|
|
|
public UserInfo getUserInfo() {}
|
|
|
|
|
|
|
|
|
|
@SaNotCheckLogin // 免登录
|
|
|
|
|
@PostMapping("/login")
|
|
|
|
|
public LoginResult login() {}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2025-10-26 20:40:23 +08:00
|
|
|
### 2. NestJS (装饰器方式) - 更像Java
|
2025-09-21 21:29:28 +08:00
|
|
|
```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<boolean> {
|
|
|
|
|
// 检查是否有 @Public() 装饰器
|
|
|
|
|
const isPublic = this.reflector.getAllAndOverride<boolean>(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/*`
|
|
|
|
|
- **其他业务接口**: 所有其他接口
|
|
|
|
|
|
|
|
|
|
### 路由路径对齐
|
|
|
|
|
|
2025-10-26 20:40:23 +08:00
|
|
|
#### Java → NestJS 路径映射
|
2025-09-21 21:29:28 +08:00
|
|
|
```typescript
|
2025-10-26 20:40:23 +08:00
|
|
|
// Java: /adminapi/sys/get/website
|
2025-09-21 21:29:28 +08:00
|
|
|
// NestJS: @Get('get/website') 在 @Controller('adminapi/sys')
|
|
|
|
|
|
2025-10-26 20:40:23 +08:00
|
|
|
// Java: /adminapi/login
|
2025-09-21 21:29:28 +08:00
|
|
|
// NestJS: @Get('login') 在 @Controller('adminapi') + @Public()
|
|
|
|
|
|
2025-10-26 20:40:23 +08:00
|
|
|
// Java: /adminapi/captcha/create
|
2025-09-21 21:29:28 +08:00
|
|
|
// 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. 路径命名规范
|
2025-10-26 20:40:23 +08:00
|
|
|
- **Java方法名**: `getWebsite()` → **NestJS路径**: `get/website`
|
|
|
|
|
- **Java方法名**: `setWebsite()` → **NestJS路径**: `set/website`
|
|
|
|
|
- **Java方法名**: `getSceneDomain()` → **NestJS路径**: `get/scene/domain`
|
2025-09-21 21:29:28 +08:00
|
|
|
|
|
|
|
|
### 验证方法
|
|
|
|
|
|
|
|
|
|
#### 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 <token>" http://localhost:3001/adminapi/sys/get/website
|
|
|
|
|
curl -H "Authorization: Bearer <token>" http://localhost:3001/adminapi/site/lists
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 总结
|
|
|
|
|
|
2025-10-26 20:40:23 +08:00
|
|
|
NestJS的认证处理方式**与Java Spring Boot相同**,使用装饰器模式:
|
2025-09-21 21:29:28 +08:00
|
|
|
|
|
|
|
|
1. **@Public()** = Java的 **@SaNotCheckLogin**
|
|
|
|
|
2. **默认需要登录** = Java的 **@SaCheckLogin**
|
|
|
|
|
3. **全局守卫** = Java的 **拦截器**
|
|
|
|
|
|
2025-10-26 20:40:23 +08:00
|
|
|
这种方式灵活且类型安全,符合现代框架的设计理念。
|