faithfm/laravel-simple-auth-tokens

为Laravel提供的简单基于令牌的认证

1.0.2 2024-05-10 02:12 UTC

This package is auto-updated.

Last update: 2024-09-10 02:52:00 UTC


README

laravel-simple-auth-tokens-logo

使用API密钥(例如:https://example.com/my/route?api_token=XXXX)进行路由认证可以通过使用Laravel内置的'token'认证驱动器来实现。

此包通过提供简单的迁移来添加所需的api_token字段到您的users表来启用此功能。

我们通常在我们的API路由上启用基于会话的(以及基于令牌的)认证,但Laravel的StartSession中间件在API客户端每次请求时都会创建新的会话(因为它通常不支持Cookie)。这可能会导致会话数量迅速增加到数千个。

为了解决这个问题,此包提供了一个替换的StartSession 中间件,当检测到请求中存在api_token=XXXX时,它会阻止创建会话。

安装 + 配置

composer require faithfm/laravel-simple-auth-tokens
php artisan migrate              # adds 'api_token' field to 'users' table

修改Models\User.php以包含新的api_token字段

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

对于从Laravel 8开始的版本,在config/auth.php中的Authentication Guards部分添加基于令牌的安全卫士。(此配置在先前版本中默认包含。)

    'guards' => [
        ...
+         'api' => [
+           'driver' => 'token',
+           'provider' => 'users',
+           'input_key' => 'api_token',       // Default value - not strictly required
+           'storage_key' => 'api_token',     // Default value - not strictly required
+           'hash' => false,                  // Default value - not strictly required
+        ],

修改App\Http\Kernel.php以替换WEB路由的StartSession中间件

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
-       // \Illuminate\Session\Middleware\StartSession::class,          // replace Laravel default with...
+       \FaithFM\SimpleAuthTokens\Http\Middleware\StartSession::class,  // ...FaithFM\SimpleAuthTokens class - which prevents creation of (numerous) session files for requests containing 'api_token=XXXX'  (ie: clients without support for cookies will normally result in creation of a session-file for every API call - potentially resulting in hundreds/thousands of session-files)
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \App\Http\Middleware\HandleInertiaRequests::class,
    ],
    ...
],

(可选)修改App\Http\Kernel.php以添加API路由的基于会话的中间件(如果您想在API路由中同时启用基于会话和基于令牌的认证)

protected $middlewareGroups = [
    ...    
    'api' => [
        // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        
+       // OPTIONAL session-related middleware for API routes - recommended by FaithFM\SimpleAuthTokens
+       \App\Http\Middleware\EncryptCookies::class,
+       \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+       \FaithFM\SimpleAuthTokens\Http\Middleware\StartSession::class,		// FaithFM\SimpleAuthTokens class
+       \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+       \App\Http\Middleware\VerifyCsrfToken::class,
    ],
],

注意

Laravel 11开始,修改bootstrap/app.php 而不是... [未完全测试]

用法

假设会话和安全卫士已被配置为分别为'web''api'(即:Laravel默认设置),您可以使用以下方式使用Laravel的正常认证方法

$loggedIn = auth('api')->check();           // check if logged in  (using helper function)
$loggedIn = Auth::guard('api')->check();    // ditto  (using Facades)
$user = auth('api')->user();                // get current User using helper function
$user = Auth::guard('api')->user();         // ditto (using Facades)

// Protect routes using 'auth' middleware
Route::get(...)->middleware('auth:api')     // use token-based 'api' guard
Route::get(...)->middleware('auth:web,api') // allow either session-based or token-based guards

当通过中间件指定了多个替代安全卫士时(例如:上面的最后一个示例),此路由中的所有认证调用都隐式地使用找到的第一个已认证的安全卫士:(中间件调用shouldUse()方法,该方法覆盖了配置的默认安全卫士。)

Route::get('/showuser', function () {
    return auth()->user();	// web  OR api guard will automatically be used depending on first authenticated guard found during middleware check
})->middleware('auth:web,api');

我们还创建了一个扩展的auth_guards()辅助函数,允许指定多个安全卫士,因为不幸的是,Laravel的guard()辅助函数和Auth::guard()外观不支持在中间件保护的路由之外使用多个安全卫士 - 即

$user = auth()->user();                 // default guard   = SUPPORTED
$user = auth('api')->user();            // specific guard  = SUPPORTED
$user = auth('web,api')->user();        // multiple guards = NOT SUPPORTED
$user = auth_guards('web,api')->user(); // multiple guards = SUPPORTED (extended helper)

工作原理

Laravel内置的'token'认证驱动器在

  • Illuminate\Auth\TokenGuard.php中定义
  • Illuminate\Auth\AuthManager.php中的createTokenDriver()方法中注册,当resolve()方法匹配到$name = 'token'的驱动器时。

'token'驱动器尝试通过以下方式认证请求

  • 查找请求参数'api_token=XXXX'(例如:https://example.com/my/route?api_token=XXXX)。
  • 尝试将提供的API密钥与users表/(User模型)中的api_token字段进行匹配。
  • 如果找到具有有效匹配api_token的用户,则认证成功

我们的FaithFM\SimpleAuthTokens\Http\Middleware\StartSession中间件按以下方式工作

  • 检测请求参数中是否存在api_token=XXXX
  • 强制Laravel会话使用基于内存的'array'驱动程序来处理请求(而不是持久化文件、数据库等驱动程序)。

注意

由于我们的StartSession中间件,一个副作用是:如果你从一个浏览器加载一个已经存在有效/已登录会话的路由,当你将api_token=XXXX请求参数添加到URL中时,这个会话将变得不可见。(即:如果指定了api_token,则认证无法回退到会话)