Ответ Access-Control-Allow-Origin с заголовком ETag, похоже, кэшируется, несмотря на то, что ответ также отличается: Происхождение

#cors #apache2 #rack-cors

Вопрос:

У меня есть API rails, обслуживающий mywebsite.com и app.mywebsite.com со стойками, настроенными так, чтобы я мог делать запросы от обоих. API находится на api.mywebsite.com.

Если я позвоню в конечную точку из mywebsite.com все работает так, как и ожидалось. Однако, если я затем сделаю тот же звонок из app.myswebsite.com Я получаю ошибку:

Access to fetch at 'https://api.mywebsite.com/api/v1/endpoint' from origin 'https://app.mywebsite.com' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://mywebsite.com' that is not equal to the supplied origin.

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

Я обнаружил, что если я очищу свой кэш, то смогу успешно позвонить из app.mywebsite.com но затем получите сообщение об ошибке от mywebsite.com:

Access to fetch at 'https://api.mywebsite.com/api/v1/endpoint' from origin 'https://mywebsite.com' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://app.mywebsite.com' that is not equal to the supplied origin.

Короче говоря, мой браузер, похоже, кэширует первый заголовок «Управление доступом-Разрешить-происхождение», который он получает.

Я читал, что мне нужно установить заголовок ответа «Варьировать», но у меня уже есть этот набор в Origin.

изменить: заголовки запросов из рабочего запроса (mywebsite.com)

 Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Type: application/json
Cookie: _my_website_session=abc123
Host: api.mywebsite.com
Origin: https://mywebsite.com
Referer: https://mywebsite.com/
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
 

заголовки ответов из рабочего запроса (mywebsite.com)

 Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE
Access-Control-Allow-Origin: https://mywebsite.com
Access-Control-Expose-Headers
Access-Control-Max-Age: 7200
Cache-Control: max-age=0, private, must-revalidate
Connection: Keep-Alive
Content-Type: application/json; charset=utf-8
Date: Fri, 22 Oct 2021 09:19:31 GMT
ETag: W/"ceb3066459b786782d836ac9e51cd349"
Keep-Alive: timeout=5, max=99
Referrer-Policy: strict-origin-when-cross-origin
Server: Apache
Set-Cookie: _my_website_session=abc123; path=/; HttpOnly
Transfer-Encoding: chunked
Vary: Origin
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-Request-Id: 8fefc93c-b320-4276-acd4-8177b7745068
X-Runtime: 0.021539
X-XSS-Protection: 1; mode=block
 

Заголовки запросов из запроса с ошибкой (app.mywebsite.com):

 Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Type: application/json
Cookie: _my_website_session=abc_123
Host: api.mywebsite.com
If-None-Match: W/"ceb3066459b786782d836ac9e51cd349"
Origin: https://app.mywebsite.com
Referer: https://app.mywebsite.com/
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
 

Заголовки ответов из запроса об ошибке (app.mywebsite.com)

 Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE
Access-Control-Allow-Origin: https://mywebsite.com
Access-Control-Expose-Headers
Access-Control-Max-Age: 7200
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/json; charset=utf-8
Date: Fri, 22 Oct 2021 09:19:32 GMT
ETag: W/"ceb3066459b786782d836ac9e51cd349"
Referrer-Policy: strict-origin-when-cross-origin
Server: Apache
Set-Cookie: _my_website_session=abc123; path=/; HttpOnly
Vary: Origin
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-Request-Id: 8fefc93c-b320-4276-acd4-8177b7745068
X-Runtime: 0.021539
X-XSS-Protection: 1; mode=block
 

Правка 2
Эта проблема существует в Chrome на Mac. В Safari все работает так, как и ожидалось
Я также вижу, что запрос правильно попадает в контроллер, проблема, похоже, заключается только в ответе в агенте пользователя.

Комментарии:

1. @sideshowbarker похоже, что это то же самое, что и этот отчет: [ссылка] bugs.chromium.org/p/chromium/issues/detail?id=983532[/ссылка] и не считается ошибкой из-за совпадения заголовков ETag.

Ответ №1:

Наконец — то я докопался до сути.

Chrome по-прежнему будет использовать кэшированный заголовок, даже если источники отличаются, а заголовок «Изменить» присутствует и установлен в «Происхождение», если метки по-прежнему совпадают.

Чтобы обойти это, либо снимите заголовок ETag, либо измените его в зависимости от источника запроса.

Комментарии:

1. Еще пара вопросов: Отправляете ли вы заголовок «Изменить ответ» в каждом отдельном ответе, который вы отправляете по этому https://api.mywebsite.com/api/v1/endpoint маршруту? Я имею в виду, не только для ответов с поддержкой CORS, но и для всех ответов, независимо от этого. Если нет, то вам нужно быть.

2. Кстати, еще одна вещь: если я не ошибаюсь, вы, похоже, отправляете один и тот же заголовок ETag, даже когда изменился другой заголовок ответа. Если какие-либо заголовки ответов изменятся, ответ должен получить другой ETag.

3. @sideshowbarker Да, сам заголовок присутствует для всех запросов от API. И да, вы правы, ETag должен измениться, если изменятся заголовки ответов. В данном случае мне не требуется кэширование, поэтому выбивающий из колеи ETag работает нормально. В долгосрочной перспективе мне, возможно, придется вернуться к этому и исправить ETag, но, надеюсь, этот ответ укажет любому, кто столкнется с той же проблемой, в правильном направлении.

4. Хорошо, да, так что bugs.chromium.org/p/chromium/issues/detail?id=983532#c7 кажется, довольно ясно, что то, что описано в вопросе, вызвано ответами, имеющими одно и то же значение заголовка ETag, несмотря на то, что у них разные значения заголовка Access-Control-Allow-Origin.