在NestJS中实现安全认证机制时,如何正确集成JWT与Passport模块?
在NestJS中实现安全认证机制时,如何正确集成JWT与Passport模块?目前按照官方文档配置后,始终返回401未授权错误,但token生成和请求头携带逻辑已确认无误。是否需要额外配置守卫或中间件?能否提供一个完整的用户登录、签发token及接口权限控制的代码示例?另外,在生产环境中如何妥善管理密钥和token的有效期?
NestJS 提供了强大的安全性支持,尤其在认证方面,常用 JWT(JSON Web Token)实现。以下是一个简单的安全认证机制教程:
-
安装依赖
使用[@nestjs](/user/nestjs)/passport
和[@nestjs](/user/nestjs)/jwt
实现认证:npm install [@nestjs](/user/nestjs)/passport passport passport-local bcryptjs [@nestjs](/user/nestjs)/jwt jsonwebtoken
-
配置策略
创建一个本地认证策略 (LocalStrategy
):import { Strategy } from 'passport-local'; import { PassportStrategy } from '[@nestjs](/user/nestjs)/passport'; import { Injectable, UnauthorizedException } from '[@nestjs](/user/nestjs)/common'; import { AuthService } from './auth.service'; [@Injectable](/user/Injectable)() export class LocalStrategy extends PassportStrategy(Strategy) { constructor(private authService: AuthService) { super(); } async validate(username: string, password: string): Promise<any> { const user = await this.authService.validateUser(username, password); if (!user) throw new UnauthorizedException(); return user; } }
-
JWT 策略
配置 JWT 认证:[@Injectable](/user/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 生成逻辑:[@Injectable](/user/Injectable)() export class AuthService { validateUser(username: string, password: string): Promise<User | null> { // 查询数据库验证用户名密码 } async login(user: any) { const payload = { username: user.username, sub: user.userId }; return { access_token: this.jwtService.sign(payload) }; } }
-
路由保护
使用[@UseGuards](/user/UseGuards)()
装饰器保护需要认证的路由:[@Get](/user/Get)('profile') [@UseGuards](/user/UseGuards)(AuthGuard('jwt')) getProfile([@Req](/user/Req)() req) { return req.user; }
通过以上步骤,你可以快速实现基于 JWT 的安全认证机制。记得妥善保管密钥并处理异常情况。
NestJS 提供了强大的安全认证机制,通常使用 JWT(JSON Web Token)来实现。首先安装必要的依赖:
npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcryptjs
然后配置 Passport 和 JWT:
- 创建一个 Auth 模块并配置策略:
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { JwtStrategy } from './jwt.strategy';
import { UsersModule } from '../users/users.module';
@Module({
imports: [UsersModule],
providers: [AuthService, JwtStrategy],
})
export class AuthModule {}
- 实现 JWT 策略:
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { jwtSecret } from '../config';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: jwtSecret,
});
}
async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
- 创建登录接口并生成 JWT:
import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
@Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
@Post('login')
async login(@Body() userDto: any) {
const token = await this.authService.login(userDto);
return { token };
}
}
- 在服务中处理密码验证和 JWT 生产:
import { Injectable } from '@nestjs/common';
import * as bcrypt from 'bcryptjs';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthService {
constructor(private jwtService: JwtService) {}
async validateUser(username: string, pass: string): Promise<any> {
// 验证用户名和密码逻辑
}
async login(user: any) {
const payload = { username: user.username, sub: user.userId };
return { access_token: this.jwtService.sign(payload) };
}
}
这样就完成了基本的认证流程。用户登录时验证身份,通过后返回 JWT,后续请求携带 JWT 进行身份验证。
NestJS 安全认证机制指南
NestJS 提供了多种安全认证机制,以下是主要实现方式:
1. JWT (JSON Web Token) 认证
// 安装依赖
// npm install @nestjs/jwt passport-jwt passport
// auth.module.ts
@Module({
imports: [
UsersModule,
PassportModule,
JwtModule.register({
secret: 'your-secret-key',
signOptions: { expiresIn: '60s' },
}),
],
providers: [AuthService, LocalStrategy, JwtStrategy],
controllers: [AuthController],
})
export class AuthModule {}
// 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 };
}
}
2. Session 认证
// main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(
session({
secret: 'my-secret',
resave: false,
saveUninitialized: false,
}),
);
app.use(passport.initialize());
app.use(passport.session());
await app.listen(3000);
}
3. OAuth2 (如 Google, Facebook 登录)
// google.strategy.ts
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor() {
super({
clientID: 'your-client-id',
clientSecret: 'your-client-secret',
callbackURL: 'http://localhost:3000/auth/google/callback',
scope: ['email', 'profile'],
});
}
}
4. API 密钥认证
// api-key.guard.ts
@Injectable()
export class ApiKeyGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const apiKey = request.headers['x-api-key'];
return apiKey === 'your-api-key';
}
}
最佳实践
- 始终使用 HTTPS
- 定期更换密钥
- 限制登录尝试次数
- 实现访问令牌刷新机制
- 使用强密码哈希算法(如 bcrypt)
- 设置适当的 CORS 策略
选择适合您应用场景的认证机制,JWT 适用于无状态 API,Session 适用于传统 Web 应用,OAuth2 适合第三方登录。