Yii2 REST 简化 BasicAuth

Yii2 REST Simplify BasicAuth

我对在 Yii2 中创建 REST api 的简单程度印象深刻。但是,我在理解基本身份验证时遇到了一些麻烦。我的需求非常简单,我希望我的解决方案能够效仿。

我这里需要基本令牌认证。我现在甚至不反对硬编码,但这是我到目前为止所做的。

我有数据库 table 来保存我的单一令牌 ApiAccess(id, access_token)

ApiAccess.php - 型号 - 注意:IDE 第一行显示语法错误

 class ApiAccess extends base\ApiAccessBase implements IdentityInterface
 {
   public static function findIdentityByAccessToken($token, $type = null)
   {
     return static::findOne(['access_token' => $token]);
   }
 }

Module.php - 在 init() 函数中

 \Yii::$app->user->enableSession = false;

我制作了一个 ApiController,每个后续名词都会扩展

ApiController.php

 use yii\rest\ActiveController;
 use yii\filters\auth\HttpBasicAuth;
 use app\models\db\ApiAccess;

 class ApiController extends ActiveController
 {
   public function behaviors()
   {
      $behaviors = parent::behaviors();
      $behaviors['authenticator'] = [
        'class' => HttpBasicAuth::className(),
      ];
     return $behaviors;
   }
 }

就目前而言,在浏览器中访问 api 端点会提示输入用户名和密码。通过 REST 客户端请求显示访问错误。

如何正确地将 HttpBasicAuth 绑定到我的 ApiAccess 模型?

如何硬编码 api 访问令牌?(第一个选项显然是最好的)

让我们观察并尝试理解 "yii" REST 的基本身份验证方式。

第一。当您向 REST 控制器添加行为时,您启用了基本身份验证:

$behaviors['authenticator'] = [
    'class' => HttpBasicAuth::className(),
  ];

就像你一样。这是什么意思?这意味着您的应用程序将解析您的授权 header。看起来像:

Authorization : Basic base64(user:password)

这是yii2的一个技巧。如果你更仔细地查看代码,你会看到 yii 使用用户字段中的 access_token,所以你的 header 应该如下所示:

Authorization : Basic base64(access_token:)

如果您想更改此行为,您可以自己解析此 header:

$behaviors['authenticator'] = [
            'class' => HttpBasicAuth::className(),
            'auth' => [$this, 'auth']
        ];
....
public function auth($username, $password)
    {
        return \app\models\User::findOne(['login' => $username, 'password' => $password]);
    }

要做的第二件事。您必须从 identityInterface 实现 findIdentityByAccessToken() 函数。 为什么你的 IDE 抱怨?

class User extends ActiveRecord implements IdentityInterface

您的用户 class 声明应如下所示。

根据您的实施和结构:

public static function findIdentityByAccessToken($token, $type = null)
   {
     return static::findOne(['access_token' => $token]);
   }

您没有 returning class 的 object 实现身份接口。

如何正确制作? 将列 access_token 添加到您的用户 table,并 return 支持您的用户模型(您可以在此处查看它的外观 - https://github.com/yiisoft/yii2-app-advanced/blob/master/common/models/User.php) 如果您这样做 - 默认代码将适用于您的 findIdentityByAccessToken() 实现。

如果您不想向用户添加字段 table - 使用 user_id,access_token 字段创建一个新字段。那么你的实现应该是这样的:

public static function findIdentityByAccessToken($token, $type = null)
   {
     $apiUser = ApiAccess::find()
        ->where(['access_token' => $token])
        ->one();
     return static::findOne(['id' => $apiUser->user_id, 'status' => self::STATUS_ACTIVE]);
   }

希望我能回答你所有的问题。