Предварительная проверка OPTIONS дает 403 с Access-Control-Allow-Origin "*"

У меня есть одностраничное приложение, обслуживаемое на одном поддомене, а api - на другом. Я получаю 403 Forbidden на предполетной проверке для отправки XHR POST в api.

Отладка в curl показывает:

 curl  -H "Host: backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com" \
 -H "Origin: http://frontend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: content-type" \
-X OPTIONS --verbose http://backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com/api/users
*   Trying 54.153.79.158...
* TCP_NODELAY set
* Connected to backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com (54.153.79.158) port 80 (#0)
> OPTIONS /api/users HTTP/1.1
> Host: backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com
> User-Agent: curl/7.54.0
> Accept: */*
> Origin: http://frontend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: content-type
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 403 Forbidden
< Date: Fri, 04 May 2018 21:16:52 GMT
< Server: Apache/2.4.27 (Red Hat) OpenSSL/1.0.1e-fips
< Cache-Control: no-cache, private
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: accept, access-control-allow-origin, content-type
< Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
< Content-Length: 18
< Content-Type: text/html; charset=UTF-8
< Set-Cookie: 45fe47f0bb613513b8e98d0599b628f9=dd4b5c95b51d6168419458748b392421; path=/; HttpOnly
* HTTP/1.0 connection set to keep alive!
< Connection: keep-alive
< 
* Connection #0 to host backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com left intact
Origin not allowed

Тем не менее, Access-Control-Allow-Origin: * в ответе предполагает, что он должен разрешить Origin: http://frontend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com названный запрос.

Если я отброшу заголовок Origin из запроса, я получу 200.

Я попытался явно настроить Access-Control-Allow-Origin на сервере, чтобы он соответствовал Origin запроса, но он также возвращает 403:

 curl  -H "Host: backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com" \
 -H "Origin: http://frontend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: content-type" \
-X OPTIONS --verbose http://backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com/api/users
*   Trying 54.153.79.158...
* TCP_NODELAY set
* Connected to backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com (54.153.79.158) port 80 (#0)
> OPTIONS /api/users HTTP/1.1
> Host: backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com
> User-Agent: curl/7.54.0
> Accept: */*
> Origin: http://frontend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: content-type
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 403 Forbidden
< Date: Fri, 04 May 2018 21:32:52 GMT
< Server: Apache/2.4.27 (Red Hat) OpenSSL/1.0.1e-fips
< Cache-Control: no-cache, private
< Access-Control-Allow-Origin: http://frontend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com
< Access-Control-Allow-Headers: accept, access-control-allow-origin, content-type
< Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
< Content-Length: 18
< Content-Type: text/html; charset=UTF-8
< Set-Cookie: 45fe47f0bb613513b8e98d0599b628f9=a913ecc9ded73c3ac76fbb38d93e15a7; path=/; HttpOnly
* HTTP/1.0 connection set to keep alive!
< Connection: keep-alive
< 
* Connection #0 to host backend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com left intact
Origin not allowed

На сервере .htaccess имеет следующую конфигурацию:

<IfModule mod_headers.c>
    Header add Access-Control-Allow-Origin "http://frontend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com"
    Header add Access-Control-Allow-Headers "accept, access-control-allow-origin, content-type"
    Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
</IfModule>

Установка Access-Control-Allow-Origin на "*" не решает проблему.

Почему ответ 403 запрещен, если источник кажется разрешенным, и как это исправить?

Спасибо!

ОБНОВИТЬ

Вот мой последний .htaccess, предназначенный для PHP-бэкэнда laravel:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>
<IfModule mod_headers.c>
    Header add Access-Control-Allow-Origin "*"
    Header add Access-Control-Allow-Headers "*"
    Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
</IfModule>

Почему вы возвращаете заголовок ответа Set-Cookie на запрос OPTIONS? Это может быть связано ... Я никогда не видел сообщения об ошибке типа Origin not allowed ...

roryhewitt 05.05.2018 21:55

Код api, который устанавливает cookie, представляет собой сторонний код Laravel, работающий за балансировщиком нагрузки. Он может устанавливать cookie для каждого ответа для привязки. Как я сказал в своем вопросе, если я не установил заголовок origin, он вернет 200. Это не означает, что файл cookie является проблемой. URL-адрес, на который я отправляю сообщения, взят со страницы «подписки» для регистрации пользователя. Так что тот факт, что он будет 200 без заголовка origin, заставляет меня думать, что это проблема CORS. Почему cookie может мешать?

simbo1905 05.05.2018 23:11

Хм. Я подозреваю, что где-то еще в бэкэнд-коде источник запрещен. Либо источники все запрещены (т. Е. Заголовок Origin запрещен), либо разрешен только указанный набор источников, и ваш не один из них. Я бы проверил этот сторонний код Laravel.

roryhewitt 07.05.2018 18:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
1 002
1

Ответы 1

Как предположил @roryhewitt в комментарии к вопросу, это не проблема apache .htaccess. Проблема заключалась в том, что приложение laravel с внутренним API выдавало 403 на любой запрос CORS.

Я удалил конфигурацию mod_headers.c и настроил модуль barryvdh/laravel-cors, используемый серверным приложением, используя переменную среды CORS_ALLOWED_ORIGINS=frontend-sjm-staging.a3c1.starter-us-west-1.openshiftapps.com. Это устанавливает allowedOrigins как показано здесь.

Другие вопросы по теме