У меня есть одностраничное приложение, обслуживаемое на одном поддомене, а 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>
Код api, который устанавливает cookie, представляет собой сторонний код Laravel, работающий за балансировщиком нагрузки. Он может устанавливать cookie для каждого ответа для привязки. Как я сказал в своем вопросе, если я не установил заголовок origin, он вернет 200. Это не означает, что файл cookie является проблемой. URL-адрес, на который я отправляю сообщения, взят со страницы «подписки» для регистрации пользователя. Так что тот факт, что он будет 200 без заголовка origin, заставляет меня думать, что это проблема CORS. Почему cookie может мешать?
Хм. Я подозреваю, что где-то еще в бэкэнд-коде источник запрещен. Либо источники все запрещены (т. Е. Заголовок Origin запрещен), либо разрешен только указанный набор источников, и ваш не один из них. Я бы проверил этот сторонний код Laravel.





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