
深入实战: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)配置不同的“入口”和“花名册”。
二、规划与模型准备
假设我们要构建一个系统,包含:
- 前台用户(User):通过浏览器登录(`web`守卫)。
- 后台管理员(Admin):通过浏览器登录,但使用独立的守卫和模型。
- 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
总结与常见问题
配置多守卫系统后,整个应用的认证边界变得非常清晰。回顾一下要点:
- 规划先行:明确需要几种用户类型和访问方式。
- 模型分离:不同类型的用户最好使用不同的模型和数据表。
- 配置驱动:在`config/auth.php`中仔细配置`guards`和`providers`的对应关系。
- 守卫指定:在任何需要认证的地方(路由、控制器、中间件、模板)显式指定守卫名称,这是避免混淆的最重要习惯。
- API优选Sanctum:对于API令牌认证,Sanctum是更现代、更安全的选择。
我遇到的一个典型坑:在管理员后台的路由中,忘记写`auth:admin`中间件,结果前台用户登录后也能访问,造成了权限漏洞。所以,显式声明守卫是必须养成的安全习惯。
多守卫系统初看复杂,但一旦理解其“入口-花名册”的思维模型,配置起来就会得心应手。它让Laravel能够优雅地支撑起复杂的企业级应用权限架构。希望这篇教程能帮你少走弯路。

评论(0)