【问题标题】:REST Api with QueryParamAuth authenticator - Yii2带有 QueryParamAuth 身份验证器的 REST Api - Yii2
【发布时间】:2016-04-05 16:53:40
【问题描述】:

我正在尝试为我的应用程序创建 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 表中添加了access_token 列,在用户模型中实现findIdentityByAccessToken() 并调用此 URL http://localhost:7872/api/v1/tk103s?access-token=abcd

当且仅当access_token 与表中的任何单个用户匹配时,此方法效果很好并返回数据。 检查QueryParamAuth类,发现QueryParamAuth::authenticate()认证成功后返回$identity

目前这个网址正在返回我的表格的全部数据。

我想要的是(认证后):

  1. 获取请求者的用户 ID/用户名。
  2. 根据该 id/username,根据 db 中的表关系,与他相关的数据。 (目前正在返回整行,但我只想要与当前请求者/用户匹配的少数行)

我试过但没有得到任何线索来捕捉身份验证后返回的用户$identity。 我知道也有可能做到这一点。帮助我创造魔法。

【问题讨论】:

    标签: rest yii2 restful-authentication


    【解决方案1】:
    1. 获取请求者的用户 ID/用户名。

    您在findIdentityByAccessToken 方法中返回的那个user 实例应该可以在您的应用程序内Yii::$app-&gt;user-&gt;identity 内的任何位置访问。并且应该包含从数据库中检索到的所有属性。这是一个使用它来检查 ActiveController 类的 checkAccess 方法中的访问的快速示例:

    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,它在 ActiveController 的所有内置操作中手动调用。想法是在从数据库中检索它之后和修改它之前将动作 ID 和模型实例传递给它,以便我们可以进行额外的检查。如果您只需要通过操作 ID 执行检查,那么 yii\filters\AccessControl 可能就足够了,但在 checkAccess 内部,您还期望获得模型实例本身,因此在构建您自己的操作或覆盖现有的操作时要注意这一点很重要。请务必像在UpdateAction.phpDeleteAction.php 中一样手动调用它。


    1. 正在返回整行,但我只想要几个 .. 与 .. 当前请求者/用户匹配

    这取决于您的数据的结构。您可以覆盖 ActiveController 的 actions 以在输出结果之前对其进行过滤,如果您正在使用它可以在相关的 SearchModel 类中处理,也可以在 model 中处理。一个快速提示可能是简单地覆盖模型中的 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,但如果您使用的是使用 Query Builder 构造 SQL 查询的操作,那么您应该手动执行过滤。

    如果使用ActiveQuery(可能更好地解释here),也可以这样做:

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

    【讨论】:

    • 很棒的家伙.. 解决方案 1 根据我的要求为我工作。但是,我无法关注第二个。但是,我确实通过创建单独的操作并使用 activedataprovider 获取所需的数据找到了解决方案。
    • 我还需要一个建议,在控制器的 checkAccess() 中检查用户访问权限是否是一种好方法?如果它通过测试,那么我将根据要求向他提供数据,否则拒绝它。这是正确的方法吗?如果不让我知道更好的请..
    • checkAccess 如果你在它应该在的地方调用它,它就很强大。 RBAC 也可能是另一种选择。它始终取决于您正在构建的内容。我刚刚更新了两个答案部分。我希望现在能得到更好的解释。
    • 还有一件事。如果您不需要在太多操作中进行过滤,或者如果您确实希望通过调用Image::find()-&gt;all() 来获取所有图像,那么像您所做的那样使用单独的 activedataprovider 创建一个单独的操作是一个比我更好的解决方案给了。
    • @Samel 感谢您的回复。现在我觉得我和 yii 更兼容了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2018-07-26
    • 2021-10-05
    • 2016-01-26
    • 2018-11-24
    • 2015-05-24
    相关资源
    最近更新 更多