NestJS 使用 JWT 进行认证的流程是怎样的?
我在学习NestJS的JWT认证流程时遇到了一些疑问:
-
如何在NestJS中正确配置JWT模块?需要安装哪些依赖包?
-
生成JWT令牌时应该包含哪些必要的信息?如何设置合理的过期时间?
-
在实际项目中,应该把令牌存储在什么地方更安全?cookie还是localStorage?
-
如何实现令牌的自动刷新机制?当令牌快过期时怎样处理比较合理?
在NestJS中实现JWT认证,通常包括以下步骤:
-
安装依赖:首先需要安装
@nestjs/jwt
和@nestjs/passport
等库。 -
配置Passport:使用Passport中间件处理JWT认证逻辑。
-
创建认证模块:
- 定义用户Schema和服务。
- 创建登录接口,验证用户信息后生成JWT令牌。
-
生成JWT令牌:使用
jsonwebtoken
库,根据用户信息生成包含exp
(过期时间)和sub
(用户ID)的JWT。 -
解析JWT:在请求头中添加
Authorization: Bearer <token>
,通过装饰器自动解析并验证JWT。 -
保护路由:使用
@UseGuards(JwtAuthGuard)
装饰器保护需要认证的路由。
示例代码:
// JwtStrategy.ts
import { Strategy, ExtractJwt } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: 'your-secret-key',
});
}
async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
完整流程包括用户登录、生成JWT、设置过期时间和路由保护。
NestJS 使用 JWT 进行认证的流程如下:
-
安装依赖:首先需要安装必要的模块,如
[@nestjs](/user/nestjs)/jwt
和[@nestjs](/user/nestjs)/passport
,以及passport-jwt
。npm install [@nestjs](/user/nestjs)/jwt [@nestjs](/user/nestjs)/passport passport-jwt jsonwebtoken --save
-
配置 Passport:创建一个
auth.strategy.ts
文件,使用PassportStrategy
实现 JWT 的验证逻辑。配置jwtFromRequest
提取 token,验证签名。 -
生成 Token:用户登录时,后端验证用户名和密码,若正确则生成 JWT 并返回给前端。
const payload = { username: user.username, sub: user.id }; const token = this.jwtService.sign(payload); return { access_token: token };
-
保护路由:使用
@UseGuards(JwtAuthGuard)
装饰器来保护需要认证的路由。JwtAuthGuard
会自动验证请求中的 token。 -
前端存储 Token:前端接收到 token 后,通常存储在
localStorage
或cookie
中,并在每次请求时添加到Authorization
头中。 -
刷新 Token(可选):为了解决 Token 过期问题,可以实现 Token 刷新机制,通过刷新 Token 获取新的访问 Token。
整个流程基于 JWT 的无状态特性,简化了服务器端的用户状态管理。
NestJS 中 JWT 认证的标准流程如下:
- 安装依赖
npm install @nestjs/jwt passport-jwt
npm install @types/passport-jwt -D
- 配置 JWT 模块 (auth.module.ts)
@Module({
imports: [
JwtModule.register({
secret: 'your-secret-key', // 实际生产环境建议使用环境变量
signOptions: { expiresIn: '60s' },
}),
],
providers: [AuthService],
})
export class AuthModule {}
- 创建认证服务 (auth.service.ts)
@Injectable()
export class AuthService {
constructor(private jwtService: JwtService) {}
async login(user: any) {
const payload = { username: user.username, sub: user.userId };
return {
access_token: this.jwtService.sign(payload),
};
}
}
- 创建策略 (jwt.strategy.ts)
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: 'your-secret-key',
});
}
async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
- 创建守卫 (jwt-auth.guard.ts)
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
- 控制器中使用 (auth.controller.ts)
@Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
@Post('login')
async login(@Body() loginDto: any) {
return this.authService.login(loginDto);
}
@UseGuards(JwtAuthGuard)
@Get('profile')
getProfile(@Request() req) {
return req.user;
}
}
使用流程:
- 客户端发送登录请求获取 JWT token
- 后续请求在 Authorization header 携带 Bearer token
- 服务器验证 token 并提取用户信息
注意:
- 实际项目中应使用环境变量管理密钥
- 建议添加 refresh token 机制
- 密码应使用 bcrypt 等库加密存储