在 yii2 中覆盖 Rest 身份验证(HttpBearerAuth)的响应

Override response of Rest authentication(HttpBearerAuth) in yii2

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

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"
}

您可以使用 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 方法处理事件并更改响应格式。

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

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 将在每个请求期间被调用。