首页 > 解决方案 > yii2中Rest身份验证(HttpBearerAuth)的覆盖响应

问题描述

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

用户模型中,覆盖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);
      }
  }
}

在控制器中,我添加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"
}

标签: phpyii2yii2-advanced-appyii-extensionsyii2-api

解决方案


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

例如,在您的 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会在每个请求期间调用。


推荐阅读