系统讲解Laravel框架中多守卫认证系统的配置与API令牌插图

深入实战:Laravel多守卫认证与API令牌的完整配置指南

在构建现代Web应用时,我们常常会遇到这样的场景:一个后台需要管理员登录,一个前台需要用户登录,同时还要为移动端提供API接口。如果所有角色都挤在默认的`web`守卫里,权限和会话管理很快就会变成一团乱麻。今天,我就结合自己多次“踩坑”和实战的经验,系统性地讲解如何在Laravel中配置多守卫(Multi-Guard)认证系统,并在此基础上无缝集成API令牌(Token)认证。

一、理解核心概念:守卫、提供者与驱动

在动手之前,我们必须厘清Laravel认证系统的三个核心概念,这是避免后续配置混乱的关键。

  • 守卫(Guard):定义了如何对每个请求进行认证。比如,`web`守卫使用Session和Cookie,`api`守卫则通常使用Token。你可以把它想象成大楼的不同入口,每个入口的检查方式不同。
  • 提供者(Provider):定义了从哪里获取用户数据。通常是你的`User`模型(使用Eloquent驱动),也可能是数据库表(使用Database驱动)。它告诉守卫:“你去那个用户表里找用户信息。”
  • 驱动(Driver):是守卫实现认证的具体技术。Laravel内置了`session`、`token`、`passport`、`sanctum`等驱动。

简单来说,守卫决定“怎么验”,提供者决定“去哪找”。多守卫系统的本质,就是为不同的用户类型(如管理员、普通用户)或不同的访问方式(如浏览器、API)配置不同的“入口”和“花名册”。

二、规划与模型准备

假设我们要构建一个系统,包含:

  1. 前台用户(User):通过浏览器登录(`web`守卫)。
  2. 后台管理员(Admin):通过浏览器登录,但使用独立的守卫和模型。
  3. API用户(User):通过令牌访问API(`api`守卫)。

首先,我们创建管理员模型和迁移文件:

php artisan make:model Admin -m

编辑生成的迁移文件,创建`admins`表:

id();
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

接着,修改`app/Models/Admin.php`模型,让其继承`Authenticatable`并实现必要的接口:

<?php
namespace AppModels;

use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
use LaravelSanctumHasApiTokens; // 如果管理员也需要API令牌则引入

class Admin extends Authenticatable
{
    use Notifiable, HasApiTokens; // 引入HasApiTokens

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];
}

踩坑提示:确保你的`User`模型也使用了`LaravelSanctumHasApiTokens` trait,这是生成API令牌的基础。如果你用的是Laravel 9+,默认已集成Sanctum。

三、核心配置:修改 auth.php 配置文件

这是整个多守卫系统的“大脑”。打开 `config/auth.php`,我们需要在 `guards` 和 `providers` 部分进行配置。

 [
        'guard' => 'web', // 默认守卫仍为web(对应前台用户)
        'passwords' => 'users',
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users', // 关联到下面的users提供者
        ],

        'admin' => [ // 新增admin守卫
            'driver' => 'session',
            'provider' => 'admins', // 关联到下面的admins提供者
        ],

        'api' => [
            'driver' => 'token', // 可以使用 'sanctum' 驱动,更现代化
            'provider' => 'users',
            'hash' => false,
        ],

        'admin-api' => [ // 新增管理员API守卫
            'driver' => 'sanctum', // 使用Sanctum驱动处理令牌
            'provider' => 'admins',
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => AppModelsUser::class, // 前台用户模型
        ],

        'admins' => [ // 新增admins提供者
            'driver' => 'eloquent',
            'model' => AppModelsAdmin::class, // 后台管理员模型
        ],
    ],
    // ... 密码重置配置部分也需要对应增加 'admins' ...
];

实战经验:这里我强烈推荐API守卫使用 `sanctum` 驱动而非旧的 `token` 驱动。Sanctum提供了更安全、更灵活的SPA和移动端认证方案,并且能很好地与多守卫协同工作。

四、构建认证控制器与路由

为管理员创建独立的登录控制器和路由。首先生成控制器:

php artisan make:controller Admin/AuthController

在控制器中实现登录逻辑,关键是指定使用 `auth('admin')` 守卫:

validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        // 重点:指定使用 'admin' 守卫进行认证尝试
        if (Auth::guard('admin')->attempt($credentials, $request->filled('remember'))) {
            $request->session()->regenerate();
            return redirect()->intended(route('admin.dashboard'));
        }

        return back()->withErrors([
            'email' => '提供的凭证不匹配。',
        ]);
    }

    public function logout(Request $request)
    {
        Auth::guard('admin')->logout(); // 指定守卫退出
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return redirect()->route('admin.login');
    }
}

接着,在路由文件(如 `routes/web.php`)中定义管理员路由组,并使用中间件指定守卫:

// 管理员前台登录路由(Session)
Route::prefix('admin')->name('admin.')->group(function () {
    Route::get('login', [AdminAuthController::class, 'showLoginForm'])->name('login');
    Route::post('login', [AdminAuthController::class, 'login']);
    Route::post('logout', [AdminAuthController::class, 'logout'])->name('logout');

    // 需要管理员身份认证的路由
    Route::middleware('auth:admin')->group(function () {
        Route::get('/dashboard', function () {
            return view('admin.dashboard');
        })->name('dashboard');
        // ... 其他管理员路由
    });
});

注意:中间件 `auth:admin` 明确要求请求必须通过 `admin` 守卫认证。

五、实现API令牌认证(以Sanctum为例)

首先,确保已安装并配置好Laravel Sanctum。然后,为用户和管理员分别创建API令牌。

1. 创建令牌控制器

validate([
            'email' => 'required|email',
            'password' => 'required',
            'device_name' => 'required', // 标识哪个设备创建的令牌
        ]);

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

        if (! $user || ! Hash::check($request->password, $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['凭证不正确。'],
            ]);
        }

        // 创建令牌,并返回明文token(只显示一次!)
        $token = $user->createToken($request->device_name)->plainTextToken;

        return response()->json(['token' => $token], 201);
    }

    public function destroy(Request $request)
    {
        // 撤销当前请求使用的令牌
        $request->user()->currentAccessToken()->delete();
        return response()->noContent();
    }
}

2. 保护API路由:在 `routes/api.php` 中:

use AppHttpControllersApiAuthTokenController;

// 公开路由:获取令牌
Route::post('/tokens', [AuthTokenController::class, 'store']);

// 受保护的路由组
Route::middleware('auth:sanctum')->group(function () {
    // 这里默认使用config/auth.php中api守卫配置的提供者(即users)
    Route::get('/user', function (Request $request) {
        return $request->user(); // 返回当前认证的User模型实例
    });
    Route::delete('/tokens', [AuthTokenController::class, 'destroy']);
});

// 管理员专属API路由组,使用自定义守卫
Route::prefix('admin')->middleware('auth:admin-api')->group(function () {
    Route::get('/profile', function (Request $request) {
        // 此时 $request->user() 是 Admin 模型实例
        return $request->user();
    });
});

关键点:在请求受`auth:sanctum`保护的API时,需要在请求头中携带:
`Authorization: Bearer {你的API令牌}`

六、中间件与Blade模板中的守卫指定

在自定义中间件或Blade模板中判断用户认证状态时,务必指定守卫,否则会使用默认的`web`守卫。

// 在控制器或中间件中
if (Auth::guard('admin')->check()) {
    // 当前是已登录的管理员
    $admin = Auth::guard('admin')->user();
}

// 在Blade模板中
@auth('admin')
    

欢迎管理员,{{ auth('admin')->user()->name }}

@endauth @guest('admin') 管理员登录 @endguest

总结与常见问题

配置多守卫系统后,整个应用的认证边界变得非常清晰。回顾一下要点:

  1. 规划先行:明确需要几种用户类型和访问方式。
  2. 模型分离:不同类型的用户最好使用不同的模型和数据表。
  3. 配置驱动:在`config/auth.php`中仔细配置`guards`和`providers`的对应关系。
  4. 守卫指定:在任何需要认证的地方(路由、控制器、中间件、模板)显式指定守卫名称,这是避免混淆的最重要习惯。
  5. API优选Sanctum:对于API令牌认证,Sanctum是更现代、更安全的选择。

我遇到的一个典型坑:在管理员后台的路由中,忘记写`auth:admin`中间件,结果前台用户登录后也能访问,造成了权限漏洞。所以,显式声明守卫是必须养成的安全习惯。

多守卫系统初看复杂,但一旦理解其“入口-花名册”的思维模型,配置起来就会得心应手。它让Laravel能够优雅地支撑起复杂的企业级应用权限架构。希望这篇教程能帮你少走弯路。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。