Yii2-Api: как передать токен для фильтра HttpBearer - PullRequest
0 голосов
/ 12 мая 2018

Вот мой контроллер

class ClientController extends ActiveController
{
    public $modelClass = 'common\models\Client'; 
    public $serializer = [
      'class' => 'yii\rest\Serializer',
      'collectionEnvelope' => 'items',
  ];
    public function behaviors()
    {

        return ArrayHelper::meenter code hererge(parent::behaviors(),[
          [
            'class' => \yii\filters\Cors::className(),
        ],
           [
           'class' => CompositeAuth::className(),
           'except' => ['options'],
           'authMethods' => [
           HttpBearerAuth::className(),
             QueryParamAuth::className(),

           ],
        ],

           [
           'class' => TimestampBehavior::className(),
           ],
             [
              'class' => 'yii\filters\ContentNegotiator',
              'only' => ['view', 'index'],  // in a controller
              // if in a module, use the following IDs for user actions
              // 'only' => ['user/view', 'user/index']
              'formats' => [
                  'application/json' => Response::FORMAT_JSON,
              ],

          ],
           [
           'class' => AccessControl::className(),
    // We will override the default rule config with the new AccessRule class
           'ruleConfig' => [
           'class' => AccessRule::className(),
           ],
           'only' => ['create', 'delete'],
           'rules' => [[
           'actions' => ['create'],
           'allow' => true,
            // Allow users, moderators and admins to create
           'roles' => [
           User::ROLE_ADMIN
           ],
        ],

           [
           'actions' => ['delete'],
           'allow' => true,
            // Allow admins to delete
           'roles' => [
           User::ROLE_ADMIN
           ],
        ],
      ],
    ],
  ]);

  }
   public function actions(){
       $actions = parent::actions();
      unset( $actions['create']);
      return $actions;
   }
   public function actionCreate(){

       $model = new \common\models\Client();
       $transaction = Yii::$app->db->beginTransaction();
       try 
       {

        $model->load(Yii::$app->getRequest()->getBodyParams(), '');
        $user_create = \common\models\User::user_create($model);
        if($user_create){
           $model->user_id = $user_create->id;
          if($model->save()){
            $transaction->commit();
            return $model;
          }
        }

       }
        catch (Exception $e) 
        {
          $transaction->rollBack();
          return null;
        }    
   }
Here is my User Model
class User extends ActiveRecord implements IdentityInterface
{

    public static function findIdentity($id)
    {
        return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
    }
    public function generateAccountActivationToken()
    {
        $this->account_activation_token = Yii::$app->security->generateRandomString() . '_' . time();
    }
    /**
     * @inheritdoc
     */
    // public static function findIdentityByAccessToken($token, $type = null)
    // {
    //     throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
    // }
    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['auth_key' => $token]);
    }
    /**
     * Finds user by username
     *
     * @param string $username
     * @return static|null
     */
    public static function findByUsername($username)
    {
        return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
    }

    /**
     * Finds user by password reset token
     *
     * @param string $token password reset token
     * @return static|null
     */
    public static function findByPasswordResetToken($token)
    {
        $expire = Yii::$app->params['user.passwordResetTokenExpire'];
        $parts = explode('_', $token);
        $timestamp = (int) end($parts);
        if ($timestamp + $expire < time()) {
            // token expired
            return null;
        }

    /**
     * @inheritdoc
     */
    public function getId()
    {
        return $this->getPrimaryKey();
    }

    /**
     * @inheritdoc
     */
    public function getAuthKey()
    {
        return $this->auth_key;
        // return null;

    }

    /**
     * @inheritdoc
     */
    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }

    /**
     * Generates "remember me" authentication key
     */
    public function generateAuthKey()
    {
        $this->auth_key = Yii::$app->security->generateRandomKey();

    }


    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if ($this->isNewRecord) {
                $this->auth_key = \Yii::$app->security->generateRandomString();
            }
            return true;
        }
        return false;
    }
}

Проблема здесь в том, что когда я отправляю запрос, он возвращает ошибку 401. Я знаю это ошибка аутентификации, она даже не попала в функцию публичная статическая функция findIdentityByAccessToken ($ token, $ type = null) { return static :: findOne (['auth_key' => $ token]); } Я знаю, что проблема здесь в HttpBearerAuth :: className (). Как я могу исправить эту ошибку, вот изображение enter image description here

1 Ответ

0 голосов
/ 12 мая 2018

Об утверждении

Он даже не приземляется на findIdentityByAccessToken()

От DOCS

После аутентификации для каждого запроса API запрашиваемый контроллер будет пытаться аутентифицировать пользователя на своем шаге beforeAction().

Если аутентификация прошла успешно, контроллер выполнит другие проверки(например, ограничение скорости, авторизация), а затем выполните действие.Информация аутентифицированного пользователя может быть получена с помощью Yii::$app->user->identity.

Если аутентификация не пройдена, ответ с HTTP-статусом 401 будет отправлен вместе с другими соответствующими заголовками (такими как заголовок WWW-Authenticate дляHTTP Basic Auth).

HttpBearerAuth extends HttpHeaderAuth, который является фильтром действий, поддерживающим HTTP-аутентификацию через HTTP Headers, посмотрите исходный код для HttpHeaderAuth функция authenticate($user, $request, $response) вы увидите, что она получает заголовки аутентификации в самой первой строке

$authHeader = $request->getHeaders()->get($this->header);

и возвращает $identity, только если authHeaders не null, в противном случае возвращается null из метода authenticate($user, $request, $response), и вы получаете ошибку 401, даже не приземлившись на findIdentityByAccesToken().

Что вам нужно сделать, это

  • Открыть postman и нажать на вкладку Authorization

enter image description here

  • Выберите Type из раскрывающегося списка BearerToken

enter image description here

  • вклсправа добавьте auth_key из пользовательской таблицы для пользователя, которому вы отправляете запрос на

enter image description here

  • Нажмитена кнопке Запрос предварительного просмотра , и вы увидите, что заголовки запроса сообщения были обновлены

enter image description here

теперь, если вы перейдете кНа вкладке Headers, которая находится совсем рядом с вкладкой Authorization, вы увидите пару key=>value заголовков авторизации

enter image description here

Теперь нажмите кнопку «Отправить» и просмотрите ваш запрос. Я рекомендую вам закомментировать все из текущего действия и просто добавить заявление echo "hello";, чтобы знать, чтоон приземлился там.


Вы можете отправить тЗаголовки через curl для аутентификации следующим образом

curl -d "param1=value1&param2=value2" 
-H "Content-Type: application/x-www-form-urlencoded" 
-H "Authorization: Bearer YOUR_TOKEN_" 
-X POST http://localhost:3000/data
...