【问题标题】:Override response of Rest authentication(HttpBearerAuth) in yii2yii2中Rest身份验证(HttpBearerAuth)的覆盖响应
【发布时间】:2019-11-04 12:33:31
【问题描述】:

我有基于令牌的授权,为此我做了以下更改。

User模型中,覆盖findIdentityByAccessToken()方法如下。

public static function findIdentityByAccessToken($token, $type = null)
{
  $userlogin = Userdevices::find()->where(['access_token' => $token])->one();

  if ($userlogin == array()) {
      return null;
  } else {
      $User = Users::findOne(['id' => $userlogin->user_id]);
      if (!count($User))
      {
          return null;
      }
      else {
          $dbUser = [
              'id' => $User->id,
          ];
          return new static($dbUser);
      }
  }
}

在Controller中,我添加behaviors()如下。

public function behaviors()
{
    $behaviors[] = [
        'class' => \yii\filters\ContentNegotiator::className(),
        'formats' => [
            'application/json' => \yii\web\Response::FORMAT_JSON,
        ],
    ];

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

    return $behaviors;
}

当 API 未获取令牌或令牌无效时,它会给出以下响应

{
    "name": "Unauthorized",
    "message": "You are requesting with an invalid credential.",
    "code": 0,
    "status": 401,
    "type": "yii\\web\\UnauthorizedHttpException"
}

我想根据我的要求更改响应,如下所示。

{
    "code": 401,
    "name": "Unauthorized",
    "is_logout": "Y",
    "status": "error",
    "message": "logout"
}

【问题讨论】:

    标签: php yii2 yii2-advanced-app yii-extensions yii2-api


    【解决方案1】:

    您可以使用yii\web\ResponsebeforeSend 事件更改响应格式。

    例如在您的 api 控制器中添加以下方法:

    public function init()
    {
        parent::init();
    
        \Yii::$app->response->on(
            \yii\web\Response::EVENT_BEFORE_SEND,
            [$this, 'beforeResponseSend']
        );
    }
    
    public function beforeResponseSend(\yii\base\Event $event)
    {
        /**
         * @var \yii\web\Response $response
         */
        $response = $event->sender;
        if ($response->data['status'] == 401) {
            $response->data = [
                'code' =>  401,
                'name' => 'Unauthorized',
                'is_logout' => 'Y',
                'status' => 'error',
                'message' => 'logout',
            ];
        }
    }
    

    控制器的init方法注册beforeSend事件。 beforeResponseSend 方法处理事件并更改响应格式。

    如果您想在多个控制器中格式化响应,最好将事件处理程序放入自己的类中,例如

    namespace app\components;
    
    class ErrorResponseHelper
    {
        public static function beforeResponseSend(Event $event)
        {
            // ... formating code ...
        }
    }
    

    并在config/web.php注册活动

    return [
        // ...
        'components' => [
            'response' => [
                'class' => 'yii\web\Response',
                'on beforeSend' => [
                    \app\components\ErrorResponseHelper::class,
                    'beforeResponseSend',
                ],
            ],
        ],
    ];     
    

    但是要小心这个解决方案,因为这样\app\components\ErrorResponseHelper::beforeResponseSend 将在每个请求期间被调用。

    【讨论】:

    • @Micheal 感谢您的回答,我尝试了两种方式,但看起来它不起作用
    • @YasinPatel 我已经用新的 yii2 基本应用程序测试了第一种方法,它运行良好。也许由于您的某些配置而无法正常工作?第二个选项只是注册事件的另一种方式,我还没有测试它,但它的注册方式与documentation 匹配,除了回调是作为类,方法对而不是闭包给出的。
    • 这两个可能都是为了自定义错误响应
    • 因为这里它在调用任何方法之前发送响应,因为用户没有登录
    • @YasinPatel 当没有正确承载令牌的请求到来时,处理应如下所示(简化): 1. 创建控制器。在该过程中调用 init() 方法,除非您已覆盖构造函数。 2. 应用过滤器。 ContentNegotiator 设置格式。 HttpBearerAuth 抛出异常。 3.错误处理程序处理异常并准备响应内容。 4. 在发送响应之前,会引发 beforeSend 事件。 5. 发送响应。在我的第一个变体中,事件在步骤 1 中注册,响应在步骤 4 中修改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    相关资源
    最近更新 更多