Files
wwjcloud/docs/AUTHENTICATION_GUIDE.md
万物街 127a4db1e3 feat: 完成sys模块迁移,对齐PHP/Java框架
- 重构sys模块架构,严格按admin/api/core分层
- 对齐所有sys实体与数据库表结构
- 实现完整的adminapi控制器,匹配PHP/Java契约
- 修复依赖注入问题,确保服务正确注册
- 添加自动迁移工具和契约验证
- 完善多租户支持和审计功能
- 统一命名规范,与PHP业务逻辑保持一致
2025-09-21 21:29:28 +08:00

178 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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<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/*`
- **其他业务接口**: 所有其他接口
### 路由路径对齐
#### 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 <token>" http://localhost:3001/adminapi/sys/get/website
curl -H "Authorization: Bearer <token>" http://localhost:3001/adminapi/site/lists
```
### 总结
NestJS的认证处理方式**更像Java Spring Boot**,使用装饰器模式:
1. **@Public()** = Java的 **@SaNotCheckLogin**
2. **默认需要登录** = Java的 **@SaCheckLogin**
3. **全局守卫** = Java的 **拦截器**
这种方式比PHP的中间件方式更加灵活和类型安全符合现代框架的设计理念。