严格遵循NestJS官方认证文档操作,调用登录接口返回401无法获取access-token
问题原因与修复方案
1. 空值判断顺序错误
你当前validateUser方法中先读取user.password再判断用户是否存在,若传入的用户名不存在,直接访问user.password会抛出异常,导致鉴权直接返回401。需调整判断顺序,同时补充缺失的username返回字段供后续生成JWT使用:
// auth.service.ts 调整后的validateUser逻辑 async validateUser(username: string, password: string): Promise<any> { const user = await this.userService.findOne(username); // 先判断用户是否存在 if (!user) { return null; } const match = await this.comparePassword(password, user.password); if (match) { // 补充返回username字段,供后续login方法使用 const { id, username, name, email, mobile, role } = user; return { id, username, name, email, mobile, role }; } return null; }
2. 环境变量读取配置错误
当前JwtModule.registerAsync直接读取process.env.JWT_SECRET,若未提前加载环境变量或ConfigModule未配置全局生效,会读取到undefined值。建议改为注入ConfigService读取配置:
// auth.module.ts 调整后的JwtModule注册逻辑 JwtModule.registerAsync({ inject: [ConfigService], useFactory: (configService: ConfigService) => ({ secret: configService.get<string>('JWT_SECRET'), signOptions: { expiresIn: '1d' }, }), }),
3. 请求参数字段名不匹配
passport-local默认从请求body中读取username和password两个字段,若你请求时传入的字段名是email/account/pwd等自定义名称,会匹配失败返回401。可以选择两种方案修复:
- 请求时严格按照
username、password字段名传参 - 在LocalStrategy中配置自定义字段映射,示例为使用email作为用户名字段:
// local.strategy.ts 调整后的构造函数 constructor(private authService: AuthService) { super({ usernameField: 'email' }); }
完成上述修改后重新测试接口即可。
内容的提问来源于stack exchange,提问作者A Depressed Man
相关产品推荐
相关产品推荐

