NestJS用户认证登录报错:Cannot read properties of undefined (reading 'username')
问题排查与解决方案
错误原因分析
核心问题
登录接口未启用Local认证守卫,导致req.user未初始化。你的AuthController中login方法的@UseGuards(AuthGuard('local'))被注释,Passport的本地认证策略无法执行,也就不会将验证后的用户对象挂载到req.user上。调用this.authService.login(req.user)时,req.user为undefined,自然无法读取username属性。
次要逻辑问题
AuthService.validateUser存在冗余判断:开头已判断if (!user) return null,后续重复的if (!user)抛出异常逻辑永远不会执行。UsersService导入的User接口与Schema定义的User类不匹配,可能引发类型校验问题。
解决方案
1. 启用LocalAuthGuard并修正接口路径
取消AuthController中守卫的注释,同时修正冗余的接口路径:
@Controller('auth') export class AuthController { constructor(private authService: AuthService) {} @UseGuards(AuthGuard('local')) // 取消注释,启用本地认证守卫 @Post('login') // 原路径/auth/auth/login重复,改为/login后接口路径为/auth/login async login(@Request() req) { return this.authService.login(req.user); } }
2. 清理AuthService冗余逻辑
删除validateUser中重复的判断,并优化用户返回结果(剔除敏感密码字段):
async validateUser(username: string, password: string): Promise<any> { const user = await this.usersService.getUser({ username }); if (!user) { throw new NotAcceptableException('could not find the user'); } const passwordValid = await bcrypt.compare(password, user.password); if (passwordValid) { const { password, ...result } = user; // 剔除密码字段 return result; } return null; }
3. 统一UsersService的User类型
将UsersService导入的User替换为Schema定义的类,确保类型一致:
// 替换原导入语句,根据你的实际文件路径调整 import { User, UserDocument } from '../schemas/user.schema'; @Injectable() export class UsersService { constructor(@InjectModel(User.name) private readonly userModel: Model<UserDocument>) {} // 调整返回类型为UserDocument async getUser(query: object ): Promise<UserDocument> { return this.userModel.findOne(query); } // 其他方法保持不变,注意返回类型统一为UserDocument }
4. 验证前端传参格式
确保前端请求/auth/login时,请求体包含username和password字段(Passport LocalStrategy默认读取这两个字段)。如果前端使用其他字段名(如email),需在LocalStrategy中配置:
@Injectable() export class LocalStrategy extends PassportStrategy(Strategy) { constructor(private authService: AuthService) { // 若前端传参为email和password,添加如下配置 // super({ usernameField: 'email' }); super(); // 默认使用username和password } // 其余逻辑不变 }
测试验证
完成修改后重启服务,调用POST /auth/login接口并传入正确的账号密码,应能正常返回access_token,不再出现Cannot read properties of undefined (reading 'username')错误。
内容的提问来源于stack exchange,提问作者Graham Morby
相关产品推荐
相关产品推荐

