выключить гребанный cors

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Аватара пользователя
ninzzo
Сообщения: 340
Зарегистрирован: 2014.04.25, 07:29

выключить гребанный cors

Сообщение ninzzo » 2018.06.20, 17:55

Создал API.
С postman и с мобилы все ходит норм, авторизация через bearer token. Работает отлично.

Делаю SPA на vue.js. Отправляю тот же post(библиотека axios) что с мобилы и postman

Получаю:
"Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8085' is therefore not allowed access. The response had HTTP status code 404."

Нашел решение что бы убрать это дерьмо cors и сделал так:

Код: Выделить всё

class RetailController extends Controller
{   
    public $modelClass = 'api\models\Userupdate';
    public $enableCsrfValidation = false;

    public static function allowedDomains() {
        return [
            '*',                       
            'http://test1.example.com',
            'http://test2.example.com',
        ];
    }


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

        // add CORS filter
        $behaviors['corsFilter'] = [
            'class' => \yii\filters\Cors::className(),
             'cors'  => [
                  // restrict access to domains:
                  'Origin'                           => static::allowedDomains(),
                  'Access-Control-Request-Method'    => ['POST'],
                  'Access-Control-Allow-Credentials' => true,
                  'Access-Control-Max-Age'           => 3600,                 // Cache (seconds)
              ],
        ];

        $behaviors['authenticator']['authMethods'] = [
              //HttpBasicAuth::className(),
              HttpBearerAuth::className(),
        ];

        $behaviors['access'] = [
            'class' => AccessControl::className(),
            'rules' => [                
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
            ],
        ];

        return $behaviors;
    }

толку 0.

Что можно сделать что бы я могу отправить post с другого домена ?!

WalpeR
Сообщения: 64
Зарегистрирован: 2016.08.29, 17:21

Re: выключить гребанный cors

Сообщение WalpeR » 2018.06.20, 20:09

404. Options нет?

Код: Выделить всё

 /**
     * @inheritdoc
     */
    public function actions()
    {
        return [
            'options' => [
                'class' => 'yii\rest\OptionsAction',
            ],
        ];
    }

Аватара пользователя
ninzzo
Сообщения: 340
Зарегистрирован: 2014.04.25, 07:29

Re: выключить гребанный cors

Сообщение ninzzo » 2018.06.20, 21:26

ДОбавил

Код: Выделить всё

public function actions()
    {
        return [
            'options' => [
                'class' => 'yii\rest\OptionsAction',
            ],
        ];
    }
Результат тот же.

Боже как же это треш....

urichalex
Сообщения: 962
Зарегистрирован: 2015.08.07, 11:03

Re: выключить гребанный cors

Сообщение urichalex » 2018.06.20, 21:32

Надо разрешить OPTIONS

Аватара пользователя
ninzzo
Сообщения: 340
Зарегистрирован: 2014.04.25, 07:29

Re: выключить гребанный cors

Сообщение ninzzo » 2018.06.20, 22:37

-разрешил OPTIONS
-добавил optionactions

Код: Выделить всё

....
use DateTime;
use yii\filters\Cors;
use yii\helpers\ArrayHelper;



class RetailController extends Controller
{   
    public $modelClass = 'api\models\Userupdate';
    public $enableCsrfValidation = false;


    public function actions()
    {
        return [
            'options' => [
                'class' => 'yii\rest\OptionsAction',
            ],
        ];
    }

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

        // add CORS filter
        $behaviors['corsFilter'] = [
            'class' => Cors::className(),
            'cors' => [
                'Origin' => [*'],
               'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
            ],
              
        ];

        $behaviors['authenticator']['authMethods'] = [
              //HttpBasicAuth::className(),
              HttpBearerAuth::className(),
        ];

        $behaviors['access'] = [
            'class' => AccessControl::className(),
            'rules' => [                
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
            ],
        ];

        return $behaviors;
    }
    ....
отправляю POST (из vue.js + axion), получаю ошибку:
OPTIONS domain/nearby_retailer 404 (Not Found)
Failed to load domain/nearby_retailer: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8088' is therefore not allowed access. The response had HTTP status code 404.

Что еще может быть? Может в каких то конфигах что то нужно указывать еще?)

urichalex
Сообщения: 962
Зарегистрирован: 2015.08.07, 11:03

Re: выключить гребанный cors

Сообщение urichalex » 2018.06.20, 23:02

Веб сервер разрешает options? у меня апач пропускал а nginx не хотел (или наоборот, не помню), пришлось в конфиге хоста указывать

urichalex
Сообщения: 962
Зарегистрирован: 2015.08.07, 11:03

Re: выключить гребанный cors

Сообщение urichalex » 2018.06.20, 23:03

И потом, у вас origin отличается? Фронт на 8088 порту а бэк на каком?

WalpeR
Сообщения: 64
Зарегистрирован: 2016.08.29, 17:21

Re: выключить гребанный cors

Сообщение WalpeR » 2018.06.21, 10:37

Код: Выделить всё

$behaviors['corsFilter'] = [
            'class' => Cors::className(),
            'cors' => [
                'Origin' => ['*'],
               'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
            ],
              
        ];
Options не обязательно добавлять. Ну тогда по очереди, на каком этапе все падает? При запросе options? Выдает 404?
Еще в cors может понадобится

Код: Выделить всё

 'Access-Control-Request-Headers' => ['*']

Аватара пользователя
ninzzo
Сообщения: 340
Зарегистрирован: 2014.04.25, 07:29

Re: выключить гребанный cors

Сообщение ninzzo » 2018.06.22, 12:10

Проблема сама в yii.

Создал на сервер файл test.php:

Код: Выделить всё

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Authorization');

   foreach (getallheaders() as $name => $value) {
            echo "$name: $value\n<br>";
        }
На него делаю POST и возвращает все мои заголовки.

Теперь делаю POST на YII2. Возвращается 404.
Смотрю в логах apache:
x.x.17.198 - - [22/Jun/2018:09:01:23 +0000] "OPTIONS /api/web/nearby_retailer HTTP/1.1" 404 385 "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36"
Да, был такой товарищ со своими OPTIONS

в index.php тоже добавил:

Код: Выделить всё

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Authorization');
header('Access-Control-Request-Headers: *');
Код контроллера:

Код: Выделить всё

use yii\filters\Cors;
use yii\helpers\ArrayHelper;

class RetailController extends Controller
{   
    public $modelClass = 'api\models\Userupdate';
    public $enableCsrfValidation = false;

    public function actions()
    {
        return [
            'options' => [
                'class' => 'yii\rest\OptionsAction',
            ],
        ];
    }
    
    public function behaviors()
    {
        $behaviors = parent::behaviors();

        // add CORS filter
        $behaviors['corsFilter'] = [
            'class' => Cors::className(),
            'cors' => [
                'Origin' => ['*'],
                'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
            ],
              
        ];

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

        $behaviors['access'] = [
            'class' => AccessControl::className(),
            'rules' => [                
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
            ],
        ];

        return $behaviors;
    }
    ....

Проблема определена - yii не пропускает OPTIONS

Может я не так прописал behaviors?

Coderius
Сообщения: 3
Зарегистрирован: 2018.06.20, 16:05
Контактная информация:

Re: выключить гребанный cors

Сообщение Coderius » 2018.06.22, 12:36

Что в логах пишет?
Ищу проекты для участия в разработке на yii2.

Аватара пользователя
ninzzo
Сообщения: 340
Зарегистрирован: 2014.04.25, 07:29

Re: выключить гребанный cors

Сообщение ninzzo » 2018.06.22, 13:55

хахаха)) ну я и тупоооой

В конфиге же:

Код: Выделить всё

...
'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'rules' => [
                ...
                'POST nearby_retailer' => 'retail/index'
                ...
             ... 
Ограничение метода только на пост)) а у нас зачем то OPTION ходит. Поставил 'nearby_retailer' => 'retail/index' и все приходит))


Правда новая ошибка
/api/web/nearby_retailer 401 (Unauthorized)
Хотя мой Authorization: Bearer token уходит правильный. НО не доходит видимо.

Логи:
2018-06-22 11:19:37 [x.37.17.198][-][-][error][yii\web\HttpException:401] yii\web\UnauthorizedHttpException: Your request was made with invalid credentials. in /var/www/html/vendor/yiisoft/yii2/filters/auth/AuthMethod.php:93
Stack trace:
#0 /var/www/html/vendor/yiisoft/yii2/filters/auth/AuthMethod.php(76): yii\filters\auth\AuthMethod->handleFailure(Object(yii\web\Response))
#1 /var/www/html/vendor/yiisoft/yii2/filters/auth/CompositeAuth.php(57): yii\filters\auth\AuthMethod->beforeAction(Object(yii\base\InlineAction))
#2 /var/www/html/vendor/yiisoft/yii2/base/ActionFilter.php(77): yii\filters\auth\CompositeAuth->beforeAction(Object(yii\base\InlineAction))
#3 [internal function]: yii\base\ActionFilter->beforeFilter(Object(yii\base\ActionEvent))
#4 /var/www/html/vendor/yiisoft/yii2/base/Component.php(627): call_user_func(Array, Object(yii\base\ActionEvent))
#5 /var/www/html/vendor/yiisoft/yii2/base/Controller.php(274): yii\base\Component->trigger('beforeAction', Object(yii\base\ActionEvent))
#6 /var/www/html/vendor/yiisoft/yii2/web/Controller.php(164): yii\base\Controller->beforeAction(Object(yii\base\InlineAction))
#7 /var/www/html/vendor/yiisoft/yii2/base/Controller.php(155): yii\web\Controller->beforeAction(Object(yii\base\InlineAction))
#8 /var/www/html/vendor/yiisoft/yii2/base/Module.php(528): yii\base\Controller->runAction('index', Array)
#9 /var/www/html/vendor/yiisoft/yii2/web/Application.php(103): yii\base\Module->runAction('retail/index', Array)
#10 /var/www/html/vendor/yiisoft/yii2/base/Application.php(386): yii\web\Application->handleRequest(Object(yii\web\Request))
#11 /var/www/html/api/web/index.php(25): yii\base\Application->run()
#12 {main}
2018-06-22 11:19:37 [x.37.17.198][-][-][info][application] $_GET = []

$_POST = [
'latitude' => '37'
'longitude' => '-123'
]

$_FILES = []

$_COOKIE = []

$_SERVER = [
'REDIRECT_STATUS' => '200'
'HTTP_HOST' => 'x.59.24.245'
'HTTP_CONNECTION' => 'keep-alive'
'CONTENT_LENGTH' => '26'
'HTTP_PRAGMA' => 'no-cache'
'HTTP_CACHE_CONTROL' => 'no-cache'
'HTTP_ACCEPT' => 'application/json, text/plain, */*'
'HTTP_ORIGIN' => 'http://localhost:8091'
'HTTP_USER_AGENT' => 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
'CONTENT_TYPE' => 'application/x-www-form-urlencoded'
'HTTP_REFERER' => 'http://localhost:8091/'
'HTTP_ACCEPT_ENCODING' => 'gzip, deflate'
'HTTP_ACCEPT_LANGUAGE' => 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,uk;q=0.6'
'HTTP_X_COMPRESS' => 'null'
'PATH' => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
'SERVER_SIGNATURE' => '<address>Apache/2.4.18 (Ubuntu) Server at 13.59.24.245 Port 80</address>
'
'SERVER_SOFTWARE' => 'Apache/2.4.18 (Ubuntu)'
'SERVER_NAME' => 'x.59.24.245'
'SERVER_ADDR' => 'x.31.35.52'
'SERVER_PORT' => '80'
'REMOTE_ADDR' => 'x.37.17.198'
'DOCUMENT_ROOT' => '/var/www/html'
'REQUEST_SCHEME' => 'http'
'CONTEXT_PREFIX' => ''
'CONTEXT_DOCUMENT_ROOT' => '/var/www/html'
'SERVER_ADMIN' => '[no address given]'
'SCRIPT_FILENAME' => '/var/www/html/api/web/index.php'
'REMOTE_PORT' => '41789'
'REDIRECT_URL' => '/api/web/nearby_retailer'
'GATEWAY_INTERFACE' => 'CGI/1.1'
'SERVER_PROTOCOL' => 'HTTP/1.1'
'REQUEST_METHOD' => 'POST'
'QUERY_STRING' => ''
'REQUEST_URI' => '/api/web/nearby_retailer'
'SCRIPT_NAME' => '/api/web/index.php'
'PHP_SELF' => '/api/web/index.php'
'REQUEST_TIME_FLOAT' => 1529666377.631
'REQUEST_TIME' => 1529666377
]
Видно что не хватает заголовка Access-Control-Allow-Headers: Authorization
но он прописал прямо в index.php и вместе с option приходит

получается уходит какой то options с заголовком authorization, потом превращается как то в post и заголовок пропадает

Аватара пользователя
ninzzo
Сообщения: 340
Зарегистрирован: 2014.04.25, 07:29

Re: выключить гребанный cors

Сообщение ninzzo » 2018.06.25, 17:01

Промучался еще 2 дня. Не мог пройтив авторизацию. Всегда получал 401.
В итоге нужно было заменить

Код: Выделить всё

$behaviors['authenticator']['authMethods'] = [
              HttpBearerAuth::className(), 
];
на

Код: Выделить всё

    unset($behaviors['authenticator']);
        $behaviors['authenticator'] = [
            'class' =>  HttpBearerAuth::className(),
        ];
Я конечно до сих пор не понимаю зачем этот unset нужен.

Выложу рабочий контроллер. Может кому то будет полезно. В гугле такая проблема очень популярна.

Код: Выделить всё

use yii\filters\Cors;
use yii\helpers\ArrayHelper;



class RetailController extends Controller
{   
    public $modelClass = 'api\models\Userupdate';
    public $enableCsrfValidation = false;

    public function actions()
    {
        return [
            'options' => [
                'class' => 'yii\rest\OptionsAction',
            ],
        ];
    }

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

        // add CORS filter
        $behaviors['corsFilter'] = [
            'class' => \yii\filters\Cors::className(),
            'cors' => [
                'Origin' => ['*'],
                'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
                'Access-Control-Allow-Credentials' => true,
            ],
              
        ];
  

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

        $behaviors['access'] = [
            'class' => AccessControl::className(),
            'rules' => [                
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
            ],
        ];

        return $behaviors;
    }
и в index.php так же нужно добавить

Код: Выделить всё

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: authorization');
header('Access-Control-Allow-Credentials: true'); 
без первой строчки работать не будет.

Всем спасибо за помощь.

Ответить