hyperf 教程之 hyperf-auth 高階用法

qbhy發表於2020-05-28

前言

上次寫了一個 hyperf-auth 元件,收到許多朋友的反饋和支援,非常感謝大家的支援。今天補充一下關於自定義使用者認證的方法。
其實,大部分場景下你都可以通過 hyperf-auth 專案的 README 文件瞭解到具體如何使用 hyperf-auth 的各種功能,但是關於自定義驗證,README 其實只是一筆帶過。
hyperf 教程之 hyperf-auth 高階用法
下面我們就來了解以下具體如何實現自定義驗證。

hyperf-auth 元件的設計思路

由於我本人是個 laravel 愛好者,所以整個元件的設計思路大致是跟 laravel auth 相似的,都有 guarduser provider,包括配置方式也是極其相似的,所以,擴充套件方式也是相似的。

自定義 guard

想要實現一個自己的 guard 非常簡單,只要實現 Qbhy\HyperfAuth\AuthGuard 介面即可,而且我抽象了一個 AbstractAuthGuard 繼承該抽象類可以減少許多程式碼,大部分情況下,你只需要實現下面這三個方法即可。

<?php

namespace App\Auth\Guard;

use Qbhy\HyperfAuth\Authenticatable;
use Qbhy\HyperfAuth\Guard\AbstractAuthGuard;

class CustomGuard extends AbstractAuthGuard
{
    public function login(Authenticatable $user)
    {
        // TODO: Implement login() method.
    }

    public function user(): ?Authenticatable
    {
        // TODO: Implement user() method.
    }

    public function logout()
    {
        // TODO: Implement logout() method.
    }
}

該類的構造方法可以注入一些 Hyperf 環境中常用的例項,比如 RequestSession。不重寫建構函式的情況下,配置檔案中的值和 guard 的屬性對應關係如下:

$authConfig = [
    'default' => [
        'guard' => 'session',
        'provider' => 'users',
    ],
    'guards' => [
        'session' => [
            'driver' => Qbhy\HyperfAuth\Guard\SessionGuard::class,
            'provider' => 'users',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => \Qbhy\HyperfAuth\Provider\EloquentProvider::class,
            'model' => App\Model\User::class, //  需要實現 Qbhy\HyperfAuth\Authenticatable 介面
        ],
    ];
    /** @var SessionGuard $guard */
    var_dump($guard->name === 'session');  // true
    var_dump($guard->config === $authConfig['guards']['session']); // true 對應gaurds裡面的value值
    var_dump($guard->userProvider); // 對應的UserProvider例項

當然,你也可以重寫建構函式,用以注入你需要用到的例項,或者設定通過自定義配置建立的例項,下面用 JwtGuard 建構函式舉例


    /** @var JWTManager */ 
    protected $jwtManager;

    /** @var RequestInterface */
    protected $request;

    /**
     * JwtGuardAbstract constructor.
     */
    public function __construct(
        array $config,
        string $name,
        UserProvider $userProvider,
        RequestInterface $request
    ) {
        parent::__construct($config, $name, $userProvider);
        $this->jwtManager = new JWTManager($config);
        $this->request = $request;
    }

自定義 user

有時候可能會給其他模型做認證功能,比如商家認證, 假設我們有 App\Model\Merchant 模型類,想要給商家加上登入認證功能,只需要實現 Qbhy\HyperfAuth\Authenticatable 介面即可。

<?php

declare (strict_types=1);

namespace App\Model;

use Hyperf\DbConnection\Model\Model;
use Qbhy\HyperfAuth\Authenticatable;

/**
 */
class Merchant extends Model implements Authenticatable
{
    public static function retrieveById($key): ?Authenticatable
    {
        // TODO: Implement retrieveById() method.
  }

    public function getId()
    {
        // TODO: Implement getId() method.
  }
}

通常情況下你只需要實現上面兩個方法即可,如果你用來做授權欄位就是主鍵的話,甚至直接使用 Qbhy\HyperfAuth\AuthAbility 這個 trait 就可以了,但是如果你用來做授權的是其他欄位,比如 token 的話,就得自己實現這倆方法了

class Merchant extends Model implements Authenticatable
{
    use AuthAbility;
}

自定義 UserProvider

大部分情況下,開發者只需要定義模型並按照上面的方法實現 Authenticatable 介面就夠用了,包括自定義資料來源。如果你要實現更為複雜的自定義使用者功能,這時候就需要自定義 UserProvider 了。你需要實現 Qbhy\HyperfAuth\UserProvider 介面。跟 自定義 guard 類似,我同樣提供了一個抽象類,直接繼承自這個抽象類即可,建構函式會傳入 $name$config ,具體例子可以參考以下程式碼。

<?php

declare(strict_types=1);

namespace Qbhy\HyperfAuth\Provider;

use Qbhy\HyperfAuth\Authenticatable;

class EloquentProvider extends AbstractUserProvider
{
    public function retrieveByCredentials($credentials)
    {
        return call_user_func_array([$this->config['model'], 'retrieveById'], [$credentials]);
    }

    public function validateCredentials(Authenticatable $user, $credentials): bool
    {
        return $user->getId() === $credentials;
    }
}

該類同樣允許重寫建構函式注入你想要的例項

結語

至此,你已經學會了自定義 hyperf-auth 的相關用法了,其實用法還是和 laravel auth 差不多的,如果還有不懂的地方可以新增 QQ群: 873213948 向我提問。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章