Передача токена-носителя в yii2 rest возвращает ошибку 401

Я использую службы angular2 и yii2 restful, но это не работает

Это моя часть angular2

In the userservice
 constructor(private http:HttpClientService, private _domaindetails:Domaindetails) { }

profile(val:string="profile"):Observable<User>{
return this.http.get(this.getUserUrl(val))
  .map(this.extractData)

 }

Это httpclientService

 createAuthorizationHeader(headers: Headers) {
  let token = JSON.parse(localStorage.getItem("currentUser")).token;
  if (token) {
    headers.append('Authorization', 'Bearer ' + token);
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Content-Type', 'application/json');
   }

  }

post(url, data) {
  let headers = new Headers();
  this.createAuthorizationHeader(headers);
 return this.http.post(url, data, {
    headers: headers
 });
}

Это мой бэкэнд в Yii2

    public function behaviors()
{
    $behaviors = parent::behaviors();
     $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::className(),
        'cors' => [
            // restrict access to
            'Origin' => ['http://localhost:4200'],
            'Access-Control-Request-Method' => ['POST', 'GET','PUT'],
            // Allow only POST and PUT methods
            'Access-Control-Request-Headers' => ['*'],
            // Allow only headers 'X-Wsse'
            // 'Access-Control-Allow-Credentials' => true,
            // Allow OPTIONS caching
            'Access-Control-Max-Age' => 3600,
            // Allow the X-Pagination-Current-Page header to be exposed to the browser.
            'Access-Control-Expose-Headers' => ['X-Pagination-Current-Page'],
        ],
    ];

    $auth = $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::className(),
        'only' => ['can-access','profile'],  //access controller
    ];

   $behaviors['authenticator']['except'] = ['options'];
    return $behaviors;
}

И действие yii2 не возвращает ошибку несанкционированного доступа

 public function actionProfile()
{

    $user = Yii::$app->user->identity;
    return ['data' => $user];
}

Когда я проверяю Yii::$app->request->headers;

введите описание изображения здесь

Как видите, токен на предъявителя установлен

Это моя юзермодель

   public static function findIdentityByAccessToken($token, $type = null)
{
    return static::findOne(['auth_key' => $token]);  //auth_key is the value used in bearer token
}

Почему он продолжает возвращать ошибку 401 несанкционированный доступ, и все же, когда я использую то же значение authkey и устанавливаю заголовки носителя авторизации в почтальоне, он работает

После нескольких исследований я обнаружил, что всякий раз, когда angular2 делает запрос, он отправляет запрос параметров, который не работает.


person Geoff    schedule 23.01.2017    source источник
comment
Вы пробовали установить поведение bearerAuth вместо аутентификатора?   -  person kyle    schedule 25.01.2017
comment
Это также не работает и возвращает неизвестный bearerAuth   -  person Geoff    schedule 25.01.2017


Ответы (2)


Для тех, кто может столкнуться с этой проблемой, я обнаружил, что это было вызвано HttpBearerAuth, и когда я перешел на QueryParamAuth, теперь все работает, я также внес несколько других изменений, как

ON THE CONTROLLER
1.Removed the cors filters

public function behaviors()
{
    $behaviors = parent::behaviors();

    $behaviors['authenticator'] = [
        'class' => CompositeAuth::className(),
        'authMethods' => [
            HttpBasicAuth::className(),
            HttpBearerAuth::className(),
            QueryParamAuth::className(),
        ],
    ];
    return $behaviors;

}

2, в моей конфигурации main.php

     'response' => [
        'format' => yii\web\Response::FORMAT_JSON,
        'charset' => 'UTF-8',
        'on beforeSend' => function ($event) {
            header("Access-Control-Allow-Origin: *");
        }
    ],
        'urlManager' => [
        'class' => 'yii\web\UrlManager',
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [
            ['class' => 'yii\rest\UrlRule', 'controller' => 'auth', 'pluralize'=>false],
            ...other controlers here
        ],

    ],

3. В файле .htacess в корне проекта я добавил

   Header set Access-Control-Allow-Origin "*"
   Header set Access-Control-Allow-Headers "Content-Type"

Итак, мой запрос на отправку angular2 выглядит как

http://127.0.0.1/bcl/api/rest/v1/auth/logout?access-token=your access token

Таким образом, токен доступа всегда передается как параметр запроса.

Основная причина в том, что я обнаружил, что если браузер отправляет какой-либо заголовок, кроме типа контента, запускается запрос параметров.

Итак, теперь мои заголовки выглядят так

headers.append('Content-Type', 'application/x-www-form-urlencoded'); 
//i removed the bearer token
person Geoff    schedule 26.01.2017

Я использовал другой подход:

Добавлен

    public function beforeAction($action)
    {
        $this->enableCsrfValidation = false;
        parent::beforeAction($action);

        if (Yii::$app->getRequest()->getMethod() === 'OPTIONS') {
            // End it, otherwise a 401 will be shown.
            Yii::$app->end();
        }

        return true;
    }

в контроллере.

Сохраните функции поведения, как указано в вашем вопросе.

Как вы упомянули, проблема в том, что браузер отправляет предварительный запрос.

Я предполагаю, что вы делаете кроссбраузерный запрос (localhost: 4200), поэтому браузер сначала делает запрос OPTIONS на сервер, чтобы узнать настройки «Access-Control-Allow», но без токена доступа в заголовке. . Таким образом, выдается 401 и процесс CORS терпит неудачу.

Разница в том, что в этом случае токен авторизации может быть указан в заголовке.

person Jannes Botis    schedule 26.01.2017
comment
Я пробовал ваш метод, но потерпел неудачу, я думаю, что поведение выполняется прежде, чем даже beforeAction - person Geoff; 28.01.2017
comment
Попробуйте установить 'Origin' = ›['*'] в поведении (), чтобы разрешить все хосты. Я вижу, что вы сделали то же самое в своем решении внутри конфигурации. В любом случае это должно соответствовать хосту angular. - person Jannes Botis; 28.01.2017