简体   繁体   中英

Override response of Rest authentication(HttpBearerAuth) in yii2

I have token based authorization, for which i have did below changes.

In User model, override findIdentityByAccessToken() method as below.

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);
      }
  }
}

In Controller, I add behaviors() as below.

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

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

    return $behaviors;
}

When API does not get token or token is not valid it gives below response

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

I want to change response as per my requirement as below.

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

You can change format of response using beforeSend event of yii\web\Response .

For example add following methods in your api controller:

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',
        ];
    }
}

The init method of controller registers the beforeSend event. The beforeResponseSend method handles the event and changes the response format.

If you want to format response in multiple controller it might be better to put the event handler into own class for example

namespace app\components;

class ErrorResponseHelper
{
    public static function beforeResponseSend(Event $event)
    {
        // ... formating code ...
    }
}

And register the event in config/web.php

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

But be careful with this solution because this way the \app\components\ErrorResponseHelper::beforeResponseSend will be called during each request.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM