CORS и кроссдоменные куки

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Аватара пользователя
bemulima
Сообщения: 207
Зарегистрирован: 2012.12.20, 09:41
Откуда: Курган

CORS и кроссдоменные куки

Сообщение bemulima »

Есть backend (http://192.168.0.201:8888) и frontend (http://192.168.0.29:3000) (next.js) на разных хостах. Когда на локалке работаю всё хорошо, так как ip один порты только разные. Но вот, как только подключусь на удаленный backend сервер начинается проблемы с cookie:
- Frontend на запросы в заголовках не добавляет cookies.
- cookie PHPSESSID, _csrf - не создаются
- из backend не создаются куки для frontend (setCookie - не работает)

Подозреваю, что CORS не правильно настроен. Есть родительский контроллер где все остальные контроллеры наследуются:

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

class Controller extends \yii\rest\Controller {

    public function behaviors()
    {
        return [
            'corsFilter' => [
                'class' => Cors::class,
                'cors' => [
                    // restrict access to
                    'Origin' => [
                        'http://192.168.0.29:3000',
                        'http://192.168.0.201:3000',
                    ],
                    'Access-Control-Allow-Headers' => [
                        'Access-Control-Allow-Headers',
                        'Origin',
                        'Accept',
                        'X-Requested-With',
                        'Content-Type',
                        'Access-Control-Request-Method',
                        'Access-Control-Request-Headers',
                        'Authorization',
                        'Refresh-Token',
                    ],
                    'Access-Control-Request-Method' => ['POST','GET','OPTIONS'],
                    'Access-Control-Request-Headers' => ['*'],
                    'Access-Control-Allow-Credentials' => true,
                    'Access-Control-Max-Age' => 3600,// Cache (seconds)
                    'Access-Control-Expose-Headers' => ['X-Pagination-Current-Page'],
                ],

            ],
            'authenticator' => [
                'class' => CompositeAuth::class,
                'authMethods' => [
                    HttpBearerAuth::class,
                ],
                'except' => ['options']
            ]
        ];
    }

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

}
В остальных контроллерах behaviors записывается:

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

public function behaviors()
	{
		$behaviors = parent::behaviors();
		$behaviors['authenticator']['except'] = [
			'index', 'get-user-subscriptions-by-uuid',
			'set-user-subscriptions-by-uuid',
            'options'
		];
		$behaviors['access'] = [
			'class' => AccessControl::class,
			'rules' => [
				[
					'allow' => true,
					'actions' => ['options'],
                    'roles' => ['@', '?'],
				],
			...
			]
		];
		$behaviors['verbs'] = [
			'class' => VerbFilter::className(),
			'actions' => [
				'get-notifications' => ['GET'],
				...
			],
		];

		return $behaviors;
	}
На фронтенде так же есть глобальный axios с настройками и все запросы выполняются через этот метод:

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

const ax = () => {
	axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
	axios.defaults.withCredentials = true;

	if (process.browser) {
		axios.defaults.headers.common['Access-Control-Allow-Headers'] = 'Set-Cookie';
		let access_token = Cookies.get('access_token');
		if (access_token) {
			axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;
		}
	}
	return axios;
};
Когда отправляется запрос идет без cookies:
Request headers:

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

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
Access-Control-Allow-Headers: Set-Cookie
Authorization: Bearer ACBSh1T-wbPzbfhqVNdSRe-DAhaXfuUve6Kzlq6G
Connection: keep-alive
Content-Length: 2
Content-Type: application/json
Host: 192.168.0.201:8888
Origin: http://192.168.0.29:3000
Referer: http://192.168.0.29:3000/
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
X-Requested-With: XMLHttpRequest
Response headers:

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

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization, Refresh-Token
Access-Control-Allow-Origin: http://192.168.0.29:3000
Access-Control-Expose-Headers: X-Pagination-Current-Page
Cache-Control: no-store, no-cache, must-revalidate
Connection: Keep-Alive
Content-Type: application/json; charset=UTF-8
Date: Mon, 03 Oct 2022 12:15:51 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive: timeout=5, max=100
Pragma: no-cache
Server: Apache/2.4.37 (AlmaLinux)
Set-Cookie: PHPSESSID=ehi6aimkfc21c9mqv1i28gvskp; path=/; HttpOnly
Set-Cookie: _csrf=Vz6iJkf7hkjlVZkdTwcP8Jxr5n7hg6q5; path=/; HttpOnly; SameSite=Lax
Transfer-Encoding: chunked
Vary: Accept
X-Debug-Duration: 25
X-Debug-Link: /debug/default/view?tag=633ad2778d4c4
X-Debug-Tag: 633ad2778d4c4
X-Powered-By: PHP/8.0.18

Где, что не так, подскажите пожалуйста!

Напомню, что, когда backend & frontend в одном хосте с разными портами - всё отлично работает: куки создаются, запросы с куками отправляются, из bakend для rontend создаются куки.
Аватара пользователя
bemulima
Сообщения: 207
Зарегистрирован: 2012.12.20, 09:41
Откуда: Курган

Re: CORS и кроссдоменные куки

Сообщение bemulima »

Решил я вопрос. Перенаправление через hosts :D .
В response headers добавились еще:

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

Access-Control-Allow-Headers: ..., crossDomain, X-Requested-With 
Access-Control-Expose-Headers: Set-Cookie
X-Requested-With: XMLHttpRequest
crossDomain: true
в /etc/hosts

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

192.168.0.201 backend.test.loc
192.168.0.29  test.loc
в .env

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

frontend_host = test.loc:3000
backend_host = backend.test.loc:8888
Теперь куки отправляются, для dev версия пойдет. На продакшне host один и тот же, по этому там проблем нет с этим.
Ответить