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

Laravel实现手机号或邮箱加密码登录时手机号登录失败如何解决

解决方案

核心问题:你当前使用了Laravel Passport的密码授权模式,Passport默认仅通过email字段校验用户身份,所以手机号登录时,虽然你自己写的Auth::attempt校验通过了,但后续调用respondToAccessTokenRequest方法时,Passport内部会再次校验凭证,无法匹配手机号对应的用户,最终返回401。

步骤1:修复迁移文件约束错误(必改,避免脏数据)

你当前的CHECK约束存在笔误,仅校验了email不为空,无法实现「phone和email不同时为空」的设计规则,修改为:

// 替换原有DB::statement行
DB::statement('ALTER TABLE users ADD CONSTRAINT chk_phone_or_email CHECK (email IS NOT NULL OR phone IS NOT NULL);');

如果已经执行过迁移,可新增一个迁移修改约束,本地开发环境也可以回滚迁移后修改再重新执行。

步骤2:自定义Passport密码授权的用户查找逻辑

在app/Providers/AuthServiceProvider.php的boot方法中添加Passport自定义用户查询规则:

use Laravel\Passport\Passport;

public function boot()
{
    $this->registerPolicies();

    // 新增以下内容
    Passport::viaRequest('password', function ($request) {
        $username = $request->get('username');
        return \App\Models\User::where('email', $username)
            ->orWhere('phone', $username)
            ->first();
    });
}

步骤3:优化登录接口代码(可选)

添加上述自定义规则后,Passport会自动处理手机号/邮箱的身份校验,你可以直接删除自行实现的循环attempt逻辑,简化代码为:

public function login(ServerRequestInterface $request)
{
    return $this->withErrorHandling(function () use ($request) {
        return $this->convertResponse(
            $this->server->respondToAccessTokenRequest($request, new Psr7Response)
        );
    });
}

如果需要保留自定义的错误提示逻辑,也可以保留原有循环,但要注意统一参数获取方式,避免混用request()助手和注入的ServerRequestInterface实例导致参数不一致:

public function login(ServerRequestInterface $request)
{
    $params = $request->getParsedBody();
    $username = $params['username'] ?? '';
    $password = $params['password'] ?? '';
    
    $loginFields = ['phone', 'email'];
    foreach ($loginFields as $field) {
        $credentials = [
            $field => $username,
            'password' => $password
        ];
        if (Auth::guard('web')->attempt($credentials)) {
            return $this->withErrorHandling(function () use ($request) {
                return $this->convertResponse(
                    $this->server->respondToAccessTokenRequest($request, new Psr7Response)
                );
            });
        }
    }

    return response()->json([
        'message' => 'Invalid username or password'
    ], 401);
}

内容的提问来源于stack exchange,提问作者Owen Kelvin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:45:03