- 重构sys模块架构,严格按admin/api/core分层 - 对齐所有sys实体与数据库表结构 - 实现完整的adminapi控制器,匹配PHP/Java契约 - 修复依赖注入问题,确保服务正确注册 - 添加自动迁移工具和契约验证 - 完善多租户支持和审计功能 - 统一命名规范,与PHP业务逻辑保持一致
4.4 KiB
4.4 KiB
NestJS 认证处理指南
认证架构对比
1. PHP ThinkPHP (传统方式)
// 通过中间件全局处理
class AdminCheckToken {
public function handle(Request $request, Closure $next) {
// 检查token,某些路由可以跳过
}
}
2. Java Spring Boot (注解方式)
@RestController
public class AuthController {
@SaCheckLogin // 需要登录
@GetMapping("/user/info")
public UserInfo getUserInfo() {}
@SaNotCheckLogin // 免登录
@PostMapping("/login")
public LoginResult login() {}
}
3. NestJS (装饰器方式) - 更像Java
@Controller('adminapi/auth')
export class AuthController {
@Public() // 免登录
@Post('login')
async login() {}
@Get('user/info') // 需要登录(默认)
async getUserInfo() {}
}
NestJS 认证处理方式
核心原则
- 默认需要登录 - 所有接口默认需要认证
- @Public()装饰器 - 标记免登录接口
- 全局守卫 - 统一处理认证逻辑
实现方式
1. 全局守卫配置
// app.module.ts
@Module({
providers: [
{ provide: APP_GUARD, useClass: GlobalAuthGuard },
],
})
export class AppModule {}
2. 全局守卫实现
// 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. 免登录装饰器
// 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 路径映射
// 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. 控制器级别设置
// 免登录控制器
@Controller('adminapi/login')
@Public() // 整个控制器免登录
export class LoginController {}
// 需要登录控制器
@Controller('adminapi/sys')
@UseGuards(JwtAuthGuard, RolesGuard) // 整个控制器需要登录
export class ConfigController {}
2. 方法级别设置
@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. 检查免登录接口
# 这些接口应该不需要token就能访问
curl http://localhost:3001/adminapi/login
curl http://localhost:3001/adminapi/captcha/create
curl http://localhost:3001/api/sys/website
2. 检查需要登录接口
# 这些接口需要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,使用装饰器模式:
- @Public() = Java的 @SaNotCheckLogin
- 默认需要登录 = Java的 @SaCheckLogin
- 全局守卫 = Java的 拦截器
这种方式比PHP的中间件方式更加灵活和类型安全,符合现代框架的设计理念。