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

Laravel 9健身APP API:管理员与用户角色登录认证故障排查

问题根源分析

你的错误核心在于对Laravel Passport的认证逻辑理解有误:

  1. Auth::attempt()是**SessionGuard(web认证守卫)**的方法,用于基于会话的登录,而Passport的TokenGuard(api认证守卫)并不支持该方法,因此抛出「Method ... does not exist」异常。
  2. Auth::guard('api')返回的是TokenGuard实例对象,你直接加括号调用(当作函数),自然会触发「Object ... is not callable」错误。
解决方案

一、先确认Passport基础配置正确

确保你已经完成Passport的初始化:

  1. 安装Passport并执行迁移:
composer require laravel/passport
php artisan migrate
php artisan passport:install
  1. 修改config/auth.php,将api守卫的driver设为passport:
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],
  1. 在User模型中引入Passport的HasApiTokens trait:
namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
    // ... 其他模型代码
}

二、登录控制器的正确写法(两种可选方案)

方案1:使用Passport密码授权客户端(符合OAuth2标准,推荐)

  1. 生成密码授权客户端,记录生成的client_id和client_secret:
php artisan passport:client --password
  1. 在.env文件中添加客户端信息:
PASSPORT_PASSWORD_CLIENT_ID=你的客户端ID
PASSPORT_PASSWORD_CLIENT_SECRET=你的客户端密钥
  1. 登录控制器代码:
namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class LoginController extends Controller
{
    public function login(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        // 调用Passport内置的密码授权端点获取令牌
        $response = Http::asForm()->post(config('app.url').'/oauth/token', [
            'grant_type' => 'password',
            'client_id' => env('PASSPORT_PASSWORD_CLIENT_ID'),
            'client_secret' => env('PASSPORT_PASSWORD_CLIENT_SECRET'),
            'username' => $request->email,
            'password' => $request->password,
            'scope' => '', // 可根据需求设置权限范围
        ]);

        if ($response->failed()) {
            return response()->json(['message' => '邮箱或密码错误'], 401);
        }

        return $response->json();
    }
}

方案2:手动验证凭证并生成令牌(适合简单场景)

直接验证用户密码,手动创建个人访问令牌:

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;

class LoginController extends Controller
{
    public function login(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        $user = User::where('email', $request->email)->first();

        // 验证密码是否匹配
        if (!$user || !password_verify($request->password, $user->password)) {
            return response()->json(['message' => '邮箱或密码错误'], 401);
        }

        // 生成API访问令牌
        $token = $user->createToken('健身APP API令牌')->accessToken;

        return response()->json([
            'token' => $token,
            'user' => $user,
            'role' => $user->role, // 假设用户表有role字段区分管理员/普通用户
        ]);
    }
}

三、AdminMiddleware的正确实现与使用

  1. 中间件代码(假设用户表用role字段标识角色,管理员值为admin):
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class AdminMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        // 先验证用户已通过API认证
        if (!Auth::guard('api')->check()) {
            return response()->json(['message' => '未授权访问'], 401);
        }

        $user = Auth::guard('api')->user();

        // 校验用户角色是否为管理员
        if ($user->role !== 'admin') {
            return response()->json(['message' => '无权限访问该资源'], 403);
        }

        return $next($request);
    }
}
  1. 在app/Http/Kernel.php中注册中间件:
protected $routeMiddleware = [
    // ... 其他中间件
    'admin' => \App\Http\Middleware\AdminMiddleware::class,
];
  1. 路由中使用中间件:
use Illuminate\Support\Facades\Route;

// 登录路由(无需认证)
Route::post('/login', [\App\Http\Controllers\Auth\LoginController::class, 'login']);

// 管理员专属路由组
Route::middleware(['auth:api', 'admin'])->group(function () {
    Route::get('/admin/dashboard', function () {
        return response()->json(['message' => '管理员面板']);
    });
    // 其他管理员路由...
});

// 普通用户路由组
Route::middleware('auth:api')->group(function () {
    Route::get('/user/profile', function () {
        return response()->json(Auth::user());
    });
    // 其他用户路由...
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 00:05:23