mpyw / null-auth
针对 Laravel 的空值保护。专为基于中间件的认证和测试设计。
v2.1.0
2024-03-13 03:41 UTC
Requires
- php: ^8.0
- illuminate/auth: ^9.0 || ^10.0 || ^11.0
- illuminate/contracts: ^9.0 || ^10.0 || ^11.0
- illuminate/support: ^9.0 || ^10.0 || ^11.0
Requires (Dev)
- mockery/mockery: ^1.3.3 || ^1.4.2
- orchestra/testbench: *
- orchestra/testbench-core: >=7.0
- phpunit/phpunit: >=9.5
README
针对 Laravel 的空值保护。专为基于中间件的认证和测试设计。
要求
- PHP:
^8.0
- Laravel:
^9.0 || ^10.0 || ^11.0
安装
composer require mpyw/null-auth
功能
NullAuthenticatable
系列
- ❗️显示包含抽象方法的。
Strict
特性在不良方法调用时抛出BadMethodCallException
。
NullGuard
NullGuard::user()
总是返回由NullGuard::setUser()
设置的已认证的用户。NullGuard::unsetUser()
可以取消用户。
NullUserProvider
- 所有方法都不做任何事情,总是返回假值。
使用方法
基本使用
编辑你的 config/auth.php
。
<?php return [ /* ... */ /* |-------------------------------------------------------------------------- | Authentication Guards |-------------------------------------------------------------------------- | | Next, you may define every authentication guard for your application. | Of course, a great default configuration has been defined for you | here which uses session storage and the Eloquent user provider. | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | Supported: "session", "token" | */ 'guards' => [ 'web' => [ 'driver' => 'null', // Use NullGuard for "web" 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', 'hash' => false, ], ], /* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | If you have multiple user tables or models you may configure multiple | sources which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' => [ 'users' => [ 'driver' => 'null', // Use NullUserProvider for "users" ], // 'users' => [ // 'driver' => 'eloquent', // 'model' => App\User::class, // ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], /* ... */ ];
动机
基于守卫的 API 认证
考虑向外部平台发送 HTTP 请求的认证。
在这种情况下,你可能通过 RequestGuard
通过 Auth::viaRequest()
调用来使用。然而,某些在合约 UserProvider
和 Authenticatable
上的方法是不可用的。它们严重依赖于以下流程
- 通过电子邮件地址从数据库检索用户
- 验证用户的密码散列
此库提供了一个帮助器,使无用的合约方法不执行任何操作;始终返回空值或假值。
现在我们在用户模型上包含 NullAuthenticatable
特性。
<?php namespace App; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Model; use Mpyw\NullAuth\NullAuthenticatable; class User extends Model implements Authenticatable { use NullAuthenticatable; }
然后只提供有效的实现 getAuthIdentifierName()
和 getAuthIdentifier()
。
<?php $user = User::find(1); // Minimal implementation for Authenticatable var_dump($user->getAuthIdentifierName()); // string(2) "id" var_dump($user->getAuthIdentifier()); // int(1) // Useless implementation for Authenticatable when we don't use StatefulGuard var_dump($user->getAuthPassword()); // string(0) "" var_dump($user->getRememberTokenName()); // string(0) "" var_dump($user->getRememberToken()); // string(0) "" $user->setRememberToken('...'); // Does nothing
基于中间件的认证
假设你讨厌使用 RequestGuard
,并希望在中间件上实现认证。
如 Auth::user()
之类的调用在每次请求第一次调用时都会产生副作用。如果你将认证集中在中间件上,并仅将 Auth::user()
作为 Authenticatable
对象的容器来使用,这可能会导致不适当的行为。
不用担心。此库提供 NullGuard
,这正好是你想要的简单的 Authenticatable
容器。 Auth::user()
不执行任何操作,只返回缓存的 Authenticatable
。你只需轻松地在你的酷中间件上调用 Auth::setUser()
即可。
<?php namespace App\Http\Middleware; use App\User; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Example\API\Authentication\Client; class AuthenticateThroughExternalAPI { /** * @var \Example\API\Authentication\Client */ protected $client; /** * @param \Example\API\Authentication\Client $client */ public function __construct(Client $client) { $this->client = $client; } /** * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { // Return user_id on success, throw AuthenticationException on failure $userId = $this->client->authenticate($request->input('token')); // Return User on success, throw ModelNotFoundException on failure $user = User::findOrFail($userId); Auth::setUser($user); return $next($request); } }
测试
不用说,它也适用于测试。不用担心会产生副作用。