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

如何实现邮箱与手机号双方式登录功能?

解决NestJS中支持邮箱与手机号双方式登录的问题

问题现状

邮箱登录功能正常,但使用手机号登录时失败,日志中发现phoneNumber参数被赋值为verified回调函数,而非前端传入的手机号。

核心问题分析

Passport LocalStrategy的validate方法参数顺序是固定的:默认第一个参数是username(对应配置的usernameField),第二个是password,第三个是Passport内置的done回调函数。你之前在validate中额外添加的phoneNumber参数,实际接收的是这个done回调,而非前端传入的手机号。此外,原配置仅指定了usernameField: 'email',导致无法正确获取手机号参数。

修复步骤

1. 修改LocalStrategy配置,开启请求对象传递

在LocalStrategy的父类构造配置中添加passReqToCallback: true,这样就能在validate方法中获取完整的请求对象,进而读取所有前端传入的参数:

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({
      passReqToCallback: true, // 允许获取request对象
      usernameField: 'email', // 保留原配置,不影响后续逻辑
    });
  }

2. 重构validate方法,从请求体获取参数

调整validate方法的参数,先获取request对象,再从req.body中提取邮箱、手机号和密码,实现动态判断:

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

    // 校验是否传入了邮箱或手机号
    if (!email && !phoneNumber) {
      throw new UnauthorizedException('请提供邮箱或手机号');
    }

    const user = await this.authService.validateUser(email, password, phoneNumber);
    
    if (!user) {
      throw new UnauthorizedException('Неверный логин или пароль');
    }
    
    return user;
  }
}

3. 优化AuthService的用户校验逻辑

确保validateUser方法能正确根据传入的邮箱或手机号查询用户,同时处理参数缺失的情况:

async validateUser(
  email: string,
  password: string,
  phoneNumber: string,
): Promise<any> {
  let user;

  if (email) {
    user = await this.usersService.findByEmail(email);
  } else if (phoneNumber) {
    user = await this.usersService.findByPhone(phoneNumber);
  } else {
    throw new UnauthorizedException('请提供邮箱或手机号');
  }

  if (!user) {
    throw new UnauthorizedException('Пользователь не найден');
  }

  const isMatch = await bcrypt.compare(password, user.password);
  if (!isMatch) {
    throw new UnauthorizedException('Не верный логи или пароль');
  }

  return user;
}

前端请求示例

  • 邮箱登录请求体:
{
  "email": "example@test.com",
  "password": "your-password"
}
  • 手机号登录请求体:
{
  "phoneNumber": "13800138000",
  "password": "your-password"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:00:57