外观
授权模块
基于 JWT + Passport 的认证授权模块,支持 Bearer Token 和自定义 Header (access-token) 提取。
模块注册
typescript
import { AuthModule } from '@maxtan/nest-core'
@Module({
imports: [
AuthModule.register({
secret: 'your-jwt-secret-key',
signOptions: {
expiresIn: '72h', // Token 有效期(默认 72h)
algorithm: 'HS256', // 签名算法(默认 HS256)
issuer: 'boot', // 发行方
audience: 'client' // 目标
},
global: true // 全局注册(默认 true)
})
]
})
export class AppModule {}保护路由
手动应用 AuthGuard
typescript
import { Controller, Get, UseGuards } from '@nestjs/common'
import { AuthGuard } from '@maxtan/nest-core'
@Controller('protected')
@UseGuards(AuthGuard)
export class ProtectedController {
@Get()
getData() {
return { message: '受保护的数据' }
}
}全局应用 AuthGuard
typescript
import { APP_GUARD } from '@nestjs/core'
import { AuthGuard, AuthModule } from '@maxtan/nest-core'
@Module({
imports: [AuthModule.register({ secret: 'your-secret' })],
providers: [
{ provide: APP_GUARD, useClass: AuthGuard }
]
})
export class AppModule {}公开路由
全局启用 AuthGuard 后,用 @AuthPublic() 标记无需认证的路由:
typescript
import { AuthPublic } from '@maxtan/nest-core'
@Controller()
export class PublicController {
@Get('health')
@AuthPublic()
healthCheck() {
return { status: 'ok' }
}
}获取用户信息
AuthDecorator 装饰器
typescript
import { AuthDecorator } from '@maxtan/nest-core'
@Controller('profile')
export class ProfileController {
// 获取完整用户信息
@Get()
getProfile(@AuthDecorator() user: AuthPayload) {
return user
}
// 获取指定字段
@Get('name')
getName(@AuthDecorator('username') username: string) {
return { username }
}
// 获取解密后的数据(如果使用了 AES 加密 payload)
@Get('data')
getData(@AuthDecorator('decryptedData') data: any) {
return data
}
}JWT Payload 结构
typescript
interface AuthPayload {
// JWT 标准字段
sub?: string // Subject(通常是用户 ID)
exp?: number // 过期时间
iat?: number // 签发时间
iss?: string // 发行方
aud?: string | string[] // 目标
// 业务字段
userId?: string // 用户 ID
username?: string // 用户名
account?: string // 账号
// AES 加密数据
jtd?: string // 加密的 JSON Token Data
decryptedData?: any // 解密后的完整数据
// 扩展字段
[key: string]: any
}AES 加密 Payload
AuthStrategy 内置了 AES 加密 payload 解密支持。在签发 Token 时,将敏感数据加密到 jtd 字段:
typescript
import { encryptAES } from '@maxtan/nest-core'
// 签发 Token
const userData = { id: '123', name: 'John', roles: ['admin'] }
const payload = {
sub: userData.id,
jtd: encryptAES(JSON.stringify(userData), jwtSecret)
}
const token = jwtService.sign(payload)AuthStrategy 自动解密 jtd 字段,结果存入 payload.decryptedData,并映射 id → userId、name → username。
解密结果使用 LRU 缓存(最多 1000 条,5 分钟过期),避免重复解密。
配置参考
AuthModuleOptions
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
secret | string | - | JWT 签名密钥(必填) |
global | boolean | true | 是否全局注册 |
signOptions | JwtSignOptions | 见下 | JWT 签名选项 |
默认签名选项:
typescript
{
algorithm: 'HS256',
expiresIn: '72h',
issuer: 'boot',
audience: 'client'
}Token 提取方式
AuthStrategy 支持两种方式提取 Token(按优先级):
Authorization: Bearer <token>— 标准 Bearer Tokenaccess-token: <token>— 自定义 Header
最佳实践
- 全局启用 AuthGuard:通过
APP_GUARD全局注册,用@AuthPublic()标记公开路由,避免遗漏保护 - JWT Secret 从环境变量读取:使用
validateEnv校验并从process.env读取,不要硬编码 - AES 加密 Payload:敏感信息使用
encryptAES加密到jtd字段,AuthStrategy 自动解密 + LRU 缓存 - Token 有效期:根据场景配置
expiresIn,API 推荐72h,后台管理可适当延长 - 公开路由最小化:
@AuthPublic()仅用于健康检查、登录等真正公开的端点 - 请求上下文自动传递:
AuthModule内置ClsModule(nestjs-cls)和RequestContextInterceptor,自动将request.user写入 CLS 上下文,任何地方可通过getCurrentUserId()/getCurrentUser()获取当前用户 - 非鉴权场景自动降级:
@AuthPublic()路由或定时任务等无 Token 场景,getCurrentUserId()返回null,审计中间件使用fallbackUserId(如'system'),不会报错
typescript
import { getCurrentUserId, getCurrentUser } from '@maxtan/nest-core'
// 在任意 Service / 工具函数中获取当前用户
const userId = getCurrentUserId() // string | null(公开路由/定时任务返回 null)
const user = getCurrentUser() // AuthPayload | undefinedtypescript
// 推荐的环境变量配置方式
import { validateEnv, zEnvStr } from '@maxtan/nest-core'
const env = validateEnv(z.object({
JWT_SECRET: zEnvStr().pipe(z.string().min(16, 'JWT_SECRET 至少 16 位')),
}))
AuthModule.register({ secret: env.JWT_SECRET })