REST Api 带有 QueryParamAuth 验证器 - Yii2

REST Api with QueryParamAuth authenticator - Yii2

我正在尝试为我的应用程序创建 rest api 以在我的 android 应用程序中获取数据。这是我的控制器

<?php

namespace api\modules\v1\controllers;

use yii\rest\ActiveController;
use yii\filters\auth\QueryParamAuth;

/**
 * Tk103 Controller API
 */
class Tk103Controller extends ActiveController
{
    public $modelClass = 'api\modules\v1\models\Tk103CurrentLocation';  

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

}

我在 user table 中添加了 access_token 列,在用户模型中实现 findIdentityByAccessToken() 并调用此 URL http://localhost:7872/api/v1/tk103s?access-token=abcd

当且仅当 access_token 与 table 中的任何 单个用户 匹配时,它才有效并返回数据。 我查看了QueryParamAuthclass,发现认证成功后QueryParamAuth::authenticate()returns$identity

目前这个 url 正在返回我的 table 的全部数据。

我要的是(认证后):

  1. 获取请求者的用户id/username。
  2. 基于那个id/username,按照数据库中tables的关系,与他相关的数据。 (目前正在返回整行,但我只想要与当前 requester/user 匹配的少数行)

我试过了,但没有得到任何线索来捕获用户在身份验证后返回的 $identity。 而且我知道也有可能完成这项工作。帮助我创造魔法。

  1. Get user id/username of the requester.

您在 findIdentityByAccessToken 方法中 return 执行的 user 实例应该可以在 Yii::$app->user->identity 中的应用内的任何位置访问。并且应该保存从数据库中检索到的所有属性。这是一个使用它来检查 checkAccess 方法中 ActiveController class:

的快速示例
public function checkAccess($action, $model = null, $params = [])
{
    // only an image owner can request the related 'delete' or 'update' actions
    if ($action === 'update' or $action === 'delete') {
        if ($model->user_id !== \Yii::$app->user->identity->id)
            throw new \yii\web\ForbiddenHttpException('You can only '.$action.' images that you\'ve added.');
    }
}

请注意 checkAccess 默认为 empty method that is manually called inside all the built-in actions in ActiveController. the Idea is to pass the action ID and the model instance to it just after retrieving it from DB and before modifying it so we can do extra checks. If you just need to perform checks by actions ID then yii\filters\AccessControl may be enough but inside checkAccess you are expecting to also get the model instance itself so it is important to note that when building your own actions or overriding existing onces. be sure to manually invoke it the same way it is done in UpdateAction.php or DeleteAction.php


  1. whole rows are being returned but I want only few .. matching with .. current requester/user

这取决于您的数据结构。您可以覆盖 ActiveController 的 actions 以在输出之前过滤结果,如果您使用一个,可以在相关的 SearchModel class 中处理或者可以在模型中处理。一个快速提示可能是简单地覆盖模型中的 find 方法:

public static function find()
{
    return parent::find()->where(['user_id' => Yii::$app->user->getId()]); // or Yii::$app->user->identity->id
}

请注意,这仅在使用 ActiveRecord 时有效。这意味着当使用这个时:

$images = Image::find()->all();

我们刚刚覆盖的 find 方法默认情况下将被过滤,在生成数据库查询之前始终包含 where 条件。另请注意,ActiveController 中的默认内置 actions 正在使用 ActiveRecords,但如果您在构建 SQL 查询时使用操作使用 Query Builder 那么你应该手动进行过滤。

如果使用 ActiveQuery (maybe better explained ) 也可以这样做:

public static function find()
{
    $query = new \app\models\Image(get_called_class());
    return $query->andWhere(['user_id' => Yii::$app->user->getId()]);
}