Laravel支持多认证守卫,通过在config/auth.php中配置多个guards和providers,可实现不同用户类型(如普通用户、管理员、API客户端)的独立认证。每个守卫指定认证驱动(如session、token)和用户数据源,例如为管理员添加admin守卫并关联Admin模型,通过Auth::guard('admin')进行登录和用户获取,路由中使用auth:admin中间件保护专属路径。适用于前后台分离、API服务、多用户模型等场景,提升安全性与代码清晰度。还可自定义用户提供者(如对接外部API)和认证守卫(如JWT、SSO),通过实现对应接口并注册到服务容器,灵活应对复杂认证需求。

Laravel支持多认证守卫,这允许你的应用同时管理不同类型的用户,比如普通用户、管理员或API客户端,各自拥有独立的认证逻辑和会话管理。核心思想是在
config/auth.php
Laravel的多认证守卫机制,其实就是为了解决“我是谁?”这个问题在不同场景下的复杂性。想象一下,一个电商平台,用户需要登录才能购物,管理员需要登录才能管理商品和订单,而移动App可能通过API令牌来验证用户身份。这些“用户”虽然都是用户,但他们的认证方式、存储位置甚至权限模型都可能大相径庭。Laravel的守卫(Guards)和提供者(Providers)就是为此而生。
在
config/auth.php
guards
providers
guards
driver
session
token
sanctum
provider
provider
例如,默认情况下,你可能会看到一个
web
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],如果你想为管理员创建一个独立的认证系统,你可以添加一个
admin
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session', // 管理员也用会话认证
'provider' => 'admins', // 但用户数据来自admins提供者
],
'api' => [
'driver' => 'token', // API用token认证
'provider' => 'users', // API用户可能和web用户是同一批
'hash' => false,
],
],接着,
providers
driver
eloquent
model
继续上面的例子,如果管理员有独立的数据库表(比如
admins
App\Models\Admin
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [ // 新增一个admins提供者
'driver' => 'eloquent',
'model' => App\Models\Admin::class, // 指向Admin模型
],
],这样一来,
admin
admins
App\Models\Admin
当你在控制器中尝试认证时,可以通过
Auth::guard('admin')->attempt($credentials)Auth::guard('admin')->user()admin
auth:admin
admin
我个人觉得,当你发现自己的应用开始出现用户角色混乱、权限管理复杂到难以维护时,多守卫就是个救星。它不仅仅是代码层面的一个配置项,更是一种架构思想,帮助我们清晰地划分不同用户群体的认证边界。
举几个常见的例子:
web
api
User
CompanyAdmin
SuperAdmin
User
总的来说,当你的应用的用户群体、认证方式或用户数据源开始多样化时,多认证守卫就成了提升代码清晰度、系统可维护性和安全性的不二选择。它让我们能够以更优雅的方式处理复杂的用户认证需求,而不是在一个单点上打补丁。
配置好多个守卫之后,关键就在于如何在实际的业务逻辑中正确地调用它们。这主要体现在登录、获取当前用户和路由保护上。
在控制器中进行登录和用户操作:
当你需要让用户通过某个特定的守卫登录时,直接调用
Auth
guard()
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
class AdminAuthController extends Controller
{
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::guard('admin')->attempt($credentials)) {
// 认证成功
return redirect()->intended('/admin/dashboard');
}
// 认证失败
return back()->withErrors([
'email' => '提供的凭据与我们的记录不符。',
]);
}
public function logout()
{
Auth::guard('admin')->logout(); // 只登出admin守卫的用户
return redirect('/admin/login');
}
public function profile()
{
// 获取当前通过admin守卫认证的用户
$admin = Auth::guard('admin')->user();
if ($admin) {
return view('admin.profile', compact('admin'));
}
return redirect('/admin/login'); // 未认证则重定向
}
}这里需要注意的是,
Auth::guard('admin')->attempt()admin
web
Auth::guard('admin')->logout()admin
Auth::user()
在路由中使用中间件保护:
Laravel的
Auth
use App\Http\Controllers\AdminAuthController;
use App\Http\Controllers\AdminDashboardController;
// 管理员登录路由
Route::get('/admin/login', [AdminAuthController::class, 'showLoginForm'])->name('admin.login');
Route::post('/admin/login', [AdminAuthController::class, 'login']);
Route::post('/admin/logout', [AdminAuthController::class, 'logout'])->name('admin.logout');
// 保护管理员后台路由组
Route::middleware(['auth:admin'])->prefix('admin')->group(function () {
Route::get('/dashboard', [AdminDashboardController::class, 'index'])->name('admin.dashboard');
Route::get('/users', [AdminDashboardController::class, 'users']);
// ... 其他管理员专属路由
});
// 普通用户路由,使用默认的web守卫(或明确指定auth:web)
Route::middleware(['auth'])->group(function () { // auth中间件默认使用config/auth.php中的default guard
Route::get('/profile', function () {
return view('user.profile', ['user' => Auth::user()]);
});
});auth:admin
admin
config/auth.php
admin
login
admin.login
app/Http/Middleware/Authenticate.php
redirectTo
理解并正确使用
Auth::guard('守卫名')auth:守卫名
这块其实是Laravel认证机制最强大也最容易被忽视的地方。很多时候,我们不应该被框架的默认实现限制住,而是要学会如何“撬动”它,让它为我们的特殊需求服务。比如,我曾经遇到一个项目,用户数据分散在好几个不同的服务里,不用自定义提供者根本没法统一认证。
自定义用户提供者(User Provider):
当你的用户数据不是存储在传统的Eloquent模型中,或者需要从外部服务、NoSQL数据库等地方获取时,你就需要自定义用户提供者。一个自定义的用户提供者需要实现
Illuminate\Contracts\Auth\UserProvider
retrieveById($identifier)
retrieveByToken($identifier, $token)
updateRememberToken(Authenticatable $user, $token)
retrieveByCredentials(array $credentials)
validateCredentials(Authenticatable $user, array $credentials)
举个例子,如果你的用户数据存储在一个外部API中:
创建自定义用户提供者类:
// app/Providers/ExternalUserProvider.php
<?php
namespace App\Providers;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
use App\Models\ExternalUser; // 假设你有一个模型来封装外部用户数据
class ExternalUserProvider implements UserProvider
{
public function retrieveById($identifier)
{
// 调用外部API获取用户数据,并封装成Authenticatable对象
$userData = $this->fetchUserFromExternalApi($identifier);
if ($userData) {
return new ExternalUser($userData);
}
return null;
}
public function retrieveByToken($identifier, $token)
{
// 实现通过token获取用户逻辑
return null; // 或者根据你的外部系统实现
}
public function updateRememberToken(Authenticatable $user, $token)
{
// 如果你的外部系统支持“记住我”功能,在这里更新
}
public function retrieveByCredentials(array $credentials)
{
// 调用外部API,根据email获取用户
$userData = $this->fetchUserFromExternalApiByEmail($credentials['email']);
if ($userData) {
return new ExternalUser($userData);
}
return null;
}
public function validateCredentials(Authenticatable $user, array $credentials)
{
// 调用外部API验证密码,或者在本地进行哈希验证
return $this->verifyPasswordWithExternalApi($user->getAuthIdentifier(), $credentials['password']);
}
// 辅助方法,模拟调用外部API
protected function fetchUserFromExternalApi($id) { /* ... */ }
protected function fetchUserFromExternalApiByEmail($email) { /* ... */ }
protected function verifyPasswordWithExternalApi($id, $password) { /* ... */ }
}ExternalUser
Illuminate\Contracts\Auth\Authenticatable
在AuthServiceProvider
// app/Providers/AuthServiceProvider.php
use Illuminate\Support\Facades\Auth;
use App\Providers\ExternalUserProvider;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Auth::provider('external', function ($app, array $config) {
return new ExternalUserProvider();
});
}
}在config/auth.php
'providers' => [
// ...
'external_users' => [
'driver' => 'external', // 使用你注册的提供者名称
],
],
'guards' => [
// ...
'external_web' => [
'driver' => 'session',
'provider' => 'external_users', // 指向新的提供者
],
],自定义认证守卫(Guard):
当你需要完全自定义认证逻辑,比如实现OAuth2、JWT认证,或者与一个复杂的单点登录(SSO)系统集成时,你可能需要自定义认证守卫。一个自定义守卫需要实现
Illuminate\Contracts\Auth\Guard
check()
guest()
user()
id()
validate()
setUser()
通常,自定义守卫会与自定义用户提供者结合使用。例如,一个JWT守卫可能在
validate()
创建自定义守卫类:
// app/Guards/JwtGuard.php
<?php
namespace App\Guards;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Http\Request;
use Firebase\JWT\JWT; // 假设使用Firebase/php-jwt
class JwtGuard implements Guard
{
use GuardHelpers;
protected $provider;
protected $request;
protected $user;
public function __construct(UserProvider $provider, Request $request)
{
$this->provider = $provider;
$this->request = $request;
}
public function user()
{
if (! is_null($this->user)) {
return $this->user;
}
$token = $this->request->bearerToken(); // 从Bearer Token中获取JWT
if (! $token) {
return null;
}
try {
$payload = JWT::decode($token, new Key(config('app.jwt_secret'), 'HS256'));
// 假设JWT payload中包含用户ID
return $this->user = $this->provider->retrieveById($payload->sub);
} catch (\Exception $e) {
return null;
}
}
public function validate(array $credentials = [])
{
// JWT通常不需要传统的用户名密码验证,令牌本身就是凭证
// 但如果你想在生成令牌前验证,可以在这里做
// 对于JWT守卫,user()方法已经包含了验证逻辑
return ! is_null($this->user());
}
// 其他Guard接口方法根据需要实现
}在AuthServiceProvider
// app/Providers/AuthServiceProvider.php
use App\Guards\JwtGuard;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Auth::extend('jwt', function ($app, $name, array $config) {
// 返回一个JwtGuard实例
return new JwtGuard(Auth::createUserProvider($config['provider']), $app['request']);
});
}
}在config/auth.php
'guards' => [
// ...
'api' => [
'driver' => 'jwt', // 使用你注册的守卫名称
'provider' => 'users', // JWT可以和现有的用户提供者结合
],
],自定义守卫和提供者是Laravel认证系统的高级扩展点,它赋予了我们极大的灵活性去适应各种复杂的认证场景。虽然实现起来需要对Laravel的认证流程有深入理解,但一旦掌握,它就能让你的应用在面对非标准认证需求时游刃有余。这不仅仅是写几行代码,更是对框架底层机制的一种“驾驭”,我觉得这才是真正的技术乐趣所在。
以上就是Laravel多认证守卫?多守卫如何配置?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号