Я создаю приложение Ionic 1, которое говорит с API REST, реализованным в CakePHP 2.8, используя JSON Web Tokens (JWT) для auth.CakePHP2: CORS Предотвращение проблем с JWT Auth
В неавторизованном состоянии мое приложение может без проблем отправлять запросы GET/POST на сервер. Однако, как только я завершаю проверку подлинности, и мое приложение отправляет заголовок authToken
вместе с каждым запросом, Angular автоматически отправляет запрос предварительной печати OPTIONS
.
В этом случае проблема начинается. Поскольку в запросе автоматического предполета нет набора заголовков authToken
, и поскольку конечная точка API требует авторизации, CakePHP отвечает перенаправлением 302 FOUND на /login
. Приложение (или браузер на этом этапе тестирования) считает это небезопасным и никогда не делает правильный запрос.
Мой вопрос: Как я могу заставить CakePHP правильно ответить на предполетные запросы OPTIONS, чтобы AngularJS знал, что он может безопасно отправлять настраиваемый заголовок на междоменный сервер?
Per this question, это то, что должно произойти:
заголовков запроса:
Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header
заголовки отклика:
Access-Control-Allow-Origin: http://yourdomain.com // Same as origin above
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header
Что я пробовал:
-Установка .htaccess
, чтобы всегда отвечать на OPTIONS
запросов с 200
. Я получаю ответ 200, но в ответе говорится, что «ваш сервер неправильно сконфигурирован», и, поскольку он не имеет соответствующих наборов заголовков, реальный запрос $http
никогда не проходит.
-Получить CakePHP, чтобы всегда отвечать определенным образом на OPTIONS
запросов. Проблема здесь заключается в том, что Cake пропускает авторизацию, пропускает попытку запуска действия контроллера и отправляет ответ HTTP 200 с соответствующим набором заголовков.
// AppController::beforeFilter();
if($this->request->is("options")){
// Send the appropriate response based on the request
}
Для любопытных, вот заголовки, которые получают обменены в ходе неудавшегося $http
запроса:
GENERAL:
Request URL:https://api.example.com/rest_users/profile.json
Request Method:OPTIONS
Status Code:302 Found
Remote Address:x.x.x.x:443
REQUEST HEADERS:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US
Access-Control-Request-Headers:authtoken
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
DNT:1
Host:api.example.com
Origin:http://x.x.x.x:8100
Pragma:no-cache
Referer:http://x.x.x.x:8100/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36
RESPONSE HEADERS:
Access-Control-Allow-Headers:Content-Type, x-xsrf-token
Access-Control-Allow-Methods:*
Access-Control-Allow-Origin:*
Access-Control-Max-Age:172800
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:20
Content-Type:text/html; charset=UTF-8
Date:Thu, 29 Dec 2016 18:51:30 GMT
Keep-Alive:timeout=15, max=99
Location:https://api.example.com/login
Server:Apache/2.2.15 (CentOS)
Vary:Accept-Encoding
X-Powered-By:PHP/5.3.3
Во-первых: Вы, вероятно, следует использовать более общий 'заголовок Authorization' вместо пользовательских' authtoken' заголовка. Во-вторых: 'Access-Control-Allow-Headers: Content-Type, x-xsrf-token' ... Я не вижу, что вам разрешено отправлять свой собственный заголовок' authtoken'; это не в разрешенном списке. Вероятно, это проблема. – TheSharpieOne
Я все равно должен был иметь заголовок 'Access-Control-Allow-Origin: x.x.x.x' (обычно IP-адрес), заданный в ответе. И это не может быть подстановочным знаком.Заголовок должен быть настроен, поскольку запросы будут отправляться из приложения. – schnauss
'Access-Control-Allow-Origin' обычно не является IP-адресом, обычно это имена доменов ... если вы не обращаетесь к своему сайту через IP (в строке URL), это будут полностью квалифицированные имена доменов. '*' отлично работает для тестирования, вы бы хотели его заблокировать позже. Но это ни здесь, ни там ... не знаю, почему вы его подняли ... Я говорил о Access-Control-Allow - ** Headers **, который в настоящее время не позволяет вам отправлять заголовок 'authtoken' и блокирует ваш запрос, поскольку он не разрешен вашей конфигурацией. – TheSharpieOne