导读:本期聚焦于小伙伴创作的《Laravel 8 API多Guard认证实战指南:实现多用户表(Users/Admins)分离鉴权》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Laravel 8 API多Guard认证实战指南:实现多用户表(Users/Admins)分离鉴权》有用,将其分享出去将是对创作者最好的鼓励。

Laravel 8 API 多表用户认证:实现多Guard策略

在现代Web应用开发中,尤其是面向服务架构(SOA)或微服务架构,一个API后端可能需要同时服务于不同类型的用户,例如普通用户、管理员、商家等。这些不同类型的用户数据通常存储在不同的数据库表中,使用统一的认证逻辑和用户模型会变得复杂且不灵活。Laravel 8提供了强大且灵活的认证系统,通过其多Guard(守卫)策略,我们可以优雅地实现基于多表的API用户认证。本文将深入探讨如何在Laravel 8中为API构建一个支持多用户表(如users表和admins表)的认证系统。

Laravel 8 API多Guard认证实战指南:实现多用户表(Users/Admins)分离鉴权

一、理解Laravel的认证核心:Guards与Providers

在开始实现之前,必须理解Laravel认证系统的两个核心概念:GuardsProviders

  • Guard(守卫):定义了如何对每个请求进行用户认证。它决定了使用哪个“提供者”来检索用户,以及如何存储认证状态(例如使用Session或Token)。常见的Guard包括web(使用Session)和api(使用Token)。

  • Provider(提供者):定义了如何从持久化存储(如数据库)中检索用户。它指定了使用哪个Eloquent模型以及对应的数据表。

默认情况下,Laravel为webapiGuard配置了同一个User模型提供者。多表认证的本质就是为不同的用户类型创建不同的Guard和Provider配对。

二、项目结构与数据准备

假设我们有一个API项目,需要同时认证来自users表的普通客户和来自admins表的管理员。

首先,创建对应的数据表和模型:

# 生成用户和管理员的迁移文件
php artisan make:migration create_users_table
php artisan make:migration create_admins_table

# 生成对应的模型
php artisan make:model User
php artisan make:model Admin

在迁移文件中定义表结构(这里为简化示例):

// database/migrations/xxxx_create_users_table.php
public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
        $table->string('password');
        $table->timestamps();
    });
}

// database/migrations/xxxx_create_admins_table.php
public function up()
{
    Schema::create('admins', function (Blueprint $table) {
        $table->id();
        $table->string('username')->unique();
        $table->string('password');
        $table->timestamps();
    });
}

运行迁移:php artisan migrate

三、配置多Guard与Provider

接下来,我们需要在config/auth.php文件中进行配置。

// config/auth.php
return [
    'defaults' => [
        'guard' => 'api', // 默认使用api守卫
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token', // 可以使用sanctum或passport,这里示例用token
            'provider' => 'users',
            'hash' => false,
        ],
        // 新增一个用于管理员的API守卫
        'admin-api' => [
            'driver' => 'token',
            'provider' => 'admins', // 指向admins提供者
            'hash' => false,
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => AppModelsUser::class, // 指向User模型
        ],
        // 新增一个用于管理员的提供者
        'admins' => [
            'driver' => 'eloquent',
            'model' => AppModelsAdmin::class, // 指向Admin模型
        ],
    ],
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
        'admins' => [
            'provider' => 'admins',
            'table' => 'admin_password_resets', // 可选,如果需要独立密码重置表
            'expire' => 60,
            'throttle' => 60,
        ],
    ],
];

四、实现用户模型与认证逻辑

确保UserAdmin模型都继承自IlluminateFoundationAuthUser并使用HasApiTokens特性(如果使用Laravel Sanctum)。为简化,我们使用Laravel自带的Token认证。

// app/Models/User.php
<?php
namespace AppModels;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
class User extends Authenticatable
{
    use Notifiable;
    protected $fillable = ['name', 'email', 'password'];
    protected $hidden = ['password', 'remember_token'];
}

// app/Models/Admin.php
<?php
namespace AppModels;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
class Admin extends Authenticatable
{
    use Notifiable;
    protected $table = 'admins'; // 显式指定表名
    protected $fillable = ['username', 'password'];
    protected $hidden = ['password', 'remember_token'];
}

五、创建认证控制器与路由

我们需要为普通用户和管理员分别创建登录和获取信息的API端点。

首先,创建控制器:

php artisan make:controller Api/Auth/UserAuthController
php artisan make:controller Api/Auth/AdminAuthController

UserAuthController中实现用户登录:

// app/Http/Controllers/Api/Auth/UserAuthController.php
<?php
namespace AppHttpControllersApiAuth;
use AppHttpControllersController;
use AppModelsUser;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
use IlluminateSupportFacadesHash;
class UserAuthController extends Controller
{
    public function login(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);
        // 使用 'api' guard 对应的 User 模型进行认证
        $credentials = $request->only('email', 'password');
        if (Auth::guard('api')->attempt($credentials)) {
            $user = Auth::guard('api')->user();
            // 生成一个简单的API令牌(生产环境建议使用Sanctum/Passport)
            $token = $user->createToken('UserAPIToken')->plainTextToken;
            return response()->json([
                'user' => $user,
                'access_token' => $token,
                'token_type' => 'Bearer',
            ]);
        }
        return response()->json(['error' => 'Unauthorized'], 401);
    }
    public function profile(Request $request)
    {
        // 此路由应通过 'auth:api' 中间件保护
        return response()->json(Auth::guard('api')->user());
    }
    public function logout(Request $request)
    {
        // 撤销当前令牌
        $request->user()->currentAccessToken()->delete();
        return response()->json(['message' => 'Successfully logged out']);
    }
}

AdminAuthController中实现管理员登录(逻辑类似,但使用不同的guard):

// app/Http/Controllers/Api/Auth/AdminAuthController.php
<?php
namespace AppHttpControllersApiAuth;
use AppHttpControllersController;
use AppModelsAdmin;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
class AdminAuthController extends Controller
{
    public function login(Request $request)
    {
        $request->validate([
            'username' => 'required|string',
            'password' => 'required',
        ]);
        // 关键:使用 'admin-api' guard 进行认证
        $credentials = $request->only('username', 'password');
        if (Auth::guard('admin-api')->attempt($credentials)) {
            $admin = Auth::guard('admin-api')->user();
            $token = $admin->createToken('AdminAPIToken')->plainTextToken;
            return response()->json([
                'admin' => $admin,
                'access_token' => $token,
                'token_type' => 'Bearer',
            ]);
        }
        return response()->json(['error' => 'Unauthorized'], 401);
    }
    public function profile(Request $request)
    {
        // 此路由应通过 'auth:admin-api' 中间件保护
        return response()->json(Auth::guard('admin-api')->user());
    }
}

接下来,在routes/api.php中定义路由:

// routes/api.php
use AppHttpControllersApiAuthUserAuthController;
use AppHttpControllersApiAuthAdminAuthController;
Route::prefix('user')->group(function () {
    Route::post('/login', [UserAuthController::class, 'login']);
    Route::middleware('auth:sanctum')->group(function () { // 如果使用Sanctum
        Route::get('/profile', [UserAuthController::class, 'profile']);
        Route::post('/logout', [UserAuthController::class, 'logout']);
    });
});
Route::prefix('admin')->group(function () {
    Route::post('/login', [AdminAuthController::class, 'login']);
    Route::middleware('auth:sanctum')->group(function () {
        Route::get('/profile', [AdminAuthController::class, 'profile']);
    });
});

注意:上述示例使用了Laravel Sanctum进行API令牌管理。你需要先安装并配置Sanctum(composer require laravel/sanctum, php artisan vendor:publish --provider="LaravelSanctumSanctumServiceProvider"),并在UserAdmin模型中使用use LaravelSanctumHasApiTokens;特性。如果你使用其他驱动(如Passport或自定义Token),请相应调整认证逻辑。

六、使用中间件保护路由

Laravel的auth中间件可以指定guard,从而保护特定用户类型的路由。

// 在控制器构造函数或路由中指定guard
Route::middleware('auth:api')->get('/user/profile', function (Request $request) {
    // 只有通过 'api' guard 认证的普通用户才能访问
    return $request->user(); // 返回 User 模型实例
});
Route::middleware('auth:admin-api')->get('/admin/dashboard', function (Request $request) {
    // 只有通过 'admin-api' guard 认证的管理员才能访问
    return $request->user(); // 返回 Admin 模型实例
});

你也可以在控制器构造函数中设置默认guard:

public function __construct()
{
    // 将此控制器下的所有方法都设置为需要 'admin-api' guard 认证
    $this->middleware('auth:admin-api');
}

七、测试API端点

使用Postman或cURL测试认证流程。

  1. 普通用户登录:向POST https://www.ipipp.com/api/user/login发送JSON请求体{"email": "user@example.com", "password": "password"}。成功后将返回包含access_token的响应。

  2. 访问受保护的用户资料:在请求头中添加Authorization: Bearer {access_token},访问GET https://www.ipipp.com/api/user/profile

  3. 管理员登录:向POST https://www.ipipp.com/api/admin/login发送JSON请求体{"username": "admin1", "password": "password"}

  4. 访问受保护的管理员资料:使用管理员的token,访问GET https://www.ipipp.com/api/admin/profile

尝试用普通用户的token访问管理员端点,应该会收到401 Unauthorized错误,因为中间件auth:admin-api会使用admin-api guard来验证token,而该token是由User模型颁发的,验证会失败。

八、总结与最佳实践

通过配置多Guard和Provider,Laravel 8能够清晰、高效地支持多表API用户认证。关键步骤总结如下:

  1. 规划用户类型:明确需要区分的用户角色及其对应的数据表。

  2. 配置auth.php:为每种用户类型定义独立的guard和provider。

  3. 创建模型:每个用户类型对应一个继承Authenticatable的Eloquent模型。

  4. 实现控制器:在登录等认证逻辑中,显式使用对应的guard(如Auth::guard('admin-api')->attempt(...))。

  5. 保护路由:使用auth:{guard-name}中间件来保护特定用户类型的路由。

  6. 选择令牌驱动:对于生产环境,强烈建议使用Laravel Sanctum或Passport来管理API令牌,它们提供了更安全、更完整的功能(如令牌作用域、过期时间)。

这种架构的优势在于职责分离清晰,扩展性强。未来如果需要加入第三种用户类型(如merchants),只需重复上述模式:创建表和模型、添加新的guard和provider配置、实现对应的控制器和路由即可,无需修改现有代码。

Laravel8API认证 多Guard策略 多用户表认证 API用户鉴权 LaravelSanctum

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。