在NestJS中实现安全认证机制时,如何正确集成JWT与Passport模块?

在NestJS中实现安全认证机制时,如何正确集成JWT与Passport模块?目前按照官方文档配置后,始终返回401未授权错误,但token生成和请求头携带逻辑已确认无误。是否需要额外配置守卫或中间件?能否提供一个完整的用户登录、签发token及接口权限控制的代码示例?另外,在生产环境中如何妥善管理密钥和token的有效期?

3 回复

NestJS 提供了强大的安全性支持,尤其在认证方面,常用 JWT(JSON Web Token)实现。以下是一个简单的安全认证机制教程:

  1. 安装依赖
    使用 [@nestjs](/user/nestjs)/passport[@nestjs](/user/nestjs)/jwt 实现认证:

    npm install [@nestjs](/user/nestjs)/passport passport passport-local bcryptjs [@nestjs](/user/nestjs)/jwt jsonwebtoken
    
  2. 配置策略
    创建一个本地认证策略 (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;
        }
    }
    
  3. 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 };
        }
    }
    
  4. 服务层
    实现用户验证逻辑和 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) };
        }
    }
    
  5. 路由保护
    使用 [@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:

  1. 创建一个 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 {}
  1. 实现 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 };
  }
}
  1. 创建登录接口并生成 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 };
  }
}
  1. 在服务中处理密码验证和 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';
  }
}

最佳实践

  1. 始终使用 HTTPS
  2. 定期更换密钥
  3. 限制登录尝试次数
  4. 实现访问令牌刷新机制
  5. 使用强密码哈希算法(如 bcrypt)
  6. 设置适当的 CORS 策略

选择适合您应用场景的认证机制,JWT 适用于无状态 API,Session 适用于传统 Web 应用,OAuth2 适合第三方登录。

回到顶部