You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS手机号登录问题:无法获取phoneNumber字段的排查求助

NestJS手机号登录无法获取phoneNumber字段问题

问题现象

  • 当请求携带email字段时,登录流程正常执行
  • 当请求携带phoneNumber字段时,登录失败,无法完成认证

排查尝试

在LocalStrategy的构造函数中添加字段映射配置,但未生效:

super({
  usernameField: "email",
  phoneField: "phoneNumber",
});

添加console.log打印参数后,仅password能获取到有效值,email和phoneNumber均为undefined。

相关代码

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({
      usernameField: "email",
      phoneField: "phoneNumber",
    });
  }

  async validate(
    email: string,
    password: string,
    phoneNumber: string,
  ): Promise<any> {
    console.log(` mail ${email}`)
    console.log(` pass ${password}`)
    console.log(` phone ${phoneNumber}`)

    const user = await this.authService.validateUser(
      email,
      password,
      phoneNumber,
    );

    if (!user) {
      throw new UnauthorizedException('Неверный логин или пароль');
    }

    return user;
  }
}

解决方案

1. 修正Strategy配置逻辑

Passport的LocalStrategy默认只支持usernameField和passwordField两个配置项,自定义的phoneField不会被识别。要获取额外字段,需开启passReqToCallback: true,让validate方法接收完整请求对象,直接从请求体提取字段:

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({
      usernameField: "email",
      passReqToCallback: true, // 关键配置:传递请求对象到validate
    });
  }

  async validate(
    req: Request, // 第一个参数为请求对象
    email: string,
    password: string,
  ): Promise<any> {
    // 从请求体中直接获取phoneNumber
    const phoneNumber = req.body.phoneNumber;
    
    console.log(` mail ${email}`)
    console.log(` pass ${password}`)
    console.log(` phone ${phoneNumber}`)

    const user = await this.authService.validateUser(
      email,
      password,
      phoneNumber,
    );

    if (!user) {
      throw new UnauthorizedException('Неверный логин или пароль');
    }

    return user;
  }
}

2. 兼容邮箱/手机号双登录(可选)

如果需要同时支持两种登录方式,可在validate中判断字段存在性,调用对应验证逻辑:

async validate(req: Request, email: string, password: string): Promise<any> {
  const { phoneNumber } = req.body;
  let user;

  if (phoneNumber) {
    user = await this.authService.validateUserByPhone(phoneNumber, password);
  } else if (email) {
    user = await this.authService.validateUserByEmail(email, password);
  } else {
    throw new UnauthorizedException('请提供邮箱或手机号');
  }

  if (!user) {
    throw new UnauthorizedException('Неверный логин или пароль');
  }

  return user;
}

3. 确认请求体解析配置

确保NestJS应用已启用请求体解析中间件(NestJS默认配置express.json()和express.urlencoded()),否则无法正确读取req.body中的字段。


内容的提问来源于stack exchange,提问作者Максим Дмитриевич

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:09:54