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

Laravel9 Sanctum分表认证后访问受保护路由报错

问题根因

报错Object of type Illuminate\Auth\AuthManager is not callable核心来自两个实现错误:

  • 自定义账号密码校验通过后,没有调用Laravel官方登录方法把匹配到的用户实例绑定到认证守卫,Sanctum中间件解析请求用户时找不到合法的用户加载回调
  • 默认Eloquent认证驱动会直接读取模型本身的密码字段,和你拆分到UserPassword表的存储结构不兼容,且现有模型方法没有实现认证契约要求的密码读取逻辑

修复步骤

1. 修正登录控制器逻辑,校验通过后主动绑定用户

你现有逻辑只通过自定义类判断账号密码是否匹配,没有把查到的用户实例注入守卫上下文,直接调用$request->user()拿不到有效登录用户,token生成逻辑虽然能写入数据库,但没有和守卫的用户解析流程打通。把控制器方法修改为如下逻辑:

public function authenticate(Request $request)
{
    $returnArray = [
        'success' => false,
        'message' => null,
        'userId' => null,
        'token' => null,
    ];

    if (Auth::check()) {
        $returnArray['message'] = 'ALREADY_LOGGED_IN';
        $returnArray['userId'] = Auth::id();
        return $returnArray;
    }

    // 匹配绑定了对应邮箱的用户
    $user = UserMeta::whereHas('emailAddressList', function($query) use ($request) {
        $query->where('emailAddress', $request->emailAddress);
    })->first();

    // 取最新密码记录做哈希校验
    $latestPassword = $user?->passwordList()->latest()->first();
    if (!$user || !$latestPassword || !Hash::check($request->password, $latestPassword->value)) {
        $returnArray['message'] = 'Invalid email address or password.';
        return $returnArray;
    }

    // 核心步骤:将用户实例登录到Sanctum守卫
    Auth::login($user);
    $token = $user->createToken('USER AUTHENTICATION TOKEN', ['*']);

    $returnArray['message'] = 'SUCCESS';
    $returnArray['success'] = true;
    $returnArray['userId'] = $user->id;
    $returnArray['token'] = $token->plainTextToken;

    return $returnArray;
}

2. 修正UserMeta模型,适配拆分表的认证逻辑

默认Eloquent用户提供者会调用模型的getAuthPassword()方法获取密码哈希,你需要重写该方法,适配密码存在关联表的结构,同时删掉原来写的错误关联取值方法:

<?php

namespace App\Models\User;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class UserMeta extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    protected $table = 'UserMeta';

    // 重写密码读取逻辑,始终取最新的有效密码哈希
    public function getAuthPassword()
    {
        return $this->passwordList()->latest()->value('value') ?? '';
    }

    public function emailAddressList()
    {
        return $this->hasMany(UserEmail::class);
    }

    public function passwordList()
    {
        return $this->hasMany(UserPassword::class);
    }
}

注意:你之前写的emailAddressLatest()、passwordLatest()方法逻辑错误,关联查询后直接读取属性不会返回正确结果,后续需要取最新邮箱/密码直接通过关联查询加value()方法取值即可。

3. 清除缓存避免旧配置干扰

执行以下命令清除框架缓存:

php artisan config:clear
php artisan cache:clear

验证说明

修改完成后重新调用登录接口获取新token,携带Authorization: Bearer {你的token}请求头访问受保护路由即可正常返回用户信息,不会再抛出callable相关错误。后续实现密码回滚逻辑时,不需要修改认证核心代码,只要调整UserPassword表中对应记录的排序权重,让回滚的密码成为最新查询结果即可自动适配校验流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 21:45:46