mpyw/scoped-auth

为用户身份验证应用特定作用域。

v2.0.2 2023-03-13 06:24 UTC

This package is auto-updated.

Last update: 2024-09-21 19:37:21 UTC


README

Build Status Coverage Status Scrutinizer Code Quality

为用户身份验证应用特定作用域。

需求

  • PHP: ^8.0
  • Laravel: ^9.0 || ^10.0

安装

通过 Composer

$ composer require mpyw/scoped-auth

对于 Fortify 用户

警告

默认的 Fortify 的 RedirectIfTwoFactorAuthenticatable 实现直接使用 UserProvider 下的内部 Model,然而,Laravel 作者出于某种原因不愿意修复它。因此,我们需要像这样配置 Fortify

CustomFortifyAuthenticator.php
<?php

namespace App\Auth;

use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Contracts\Auth\UserProvider;
use Laravel\Fortify\Fortify;

class CustomFortifyAuthenticator
{
    private const PASSWORD_NAME = 'password';

    private readonly UserProvider $provider;

    public function __construct(StatefulGuard $guard)
    {
        // Assert `StatefulGuard` has `getProvider()` which is not declared in the contract
        assert(method_exists($guard, 'getProvider'));
        $provider = $guard->getProvider();

        assert($provider instanceof UserProvider);
        $this->provider = $provider;
    }

    public function __invoke(Request $request): ?Authenticatable
    {
        $user = $this->provider->retrieveByCredentials([
            Fortify::username() => $request->input(Fortify::username()),
        ]);

        return $user && $this->provider->validateCredentials($user, [
            self::PASSWORD_NAME => $request->input(self::PASSWORD_NAME),
        ]) ? $user : null;
    }
}
AuthServiceProvider.php
<?php

namespace App\Providers;

use App\Auth\CustomFortifyAuthenticator;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;

class AuthServiceProvider extends ServiceProvider
{
    public function boot(CustomFortifyAuthenticator $authenticator): void
    {
        Fortify::authenticateUsing($authenticator);
    }
}

测试

通过 PHPUnit

$ composer test

用法

在你的 Authenticatable Eloquent 模型上实现 AuthScopable 接口。

<?php

namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mpyw\ScopedAuth\AuthScopable;

class User extends Model implements UserContract, AuthScopable
{
    use Authenticatable;

    public function scopeForAuthentication(Builder $query): Builder
    {
        return $query->where('active', 1);
    }
}
<?php

use Illuminate\Support\Facades\Auth;

$user = Auth::user(); // Only include users where "active" is 1

注意,你可以重用另一个现有的作用域。

public function scopeActive(Builder $query): Builder
{
    return $query->where('active', 1);
}

public function scopeForAuthentication(Builder $query): Builder
{
    return $this->scopeActive($query);
}

作为副产品,你还可以根据标准的 Eloquent 方式执行作用域查询。

$user = User::where('email', 'xxx@example.com')->forAuthentication()->firstOrFail();
$user = User::where('email', 'xxx@example.com')->scopes(['forAuthentication'])->firstOrFail();

标准

致谢

许可

MIT 许可下授权。更多信息请参阅 许可文件