2016-12-29 3 views
2

Я создаю приложение 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 
+0

Во-первых: Вы, вероятно, следует использовать более общий 'заголовок Authorization' вместо пользовательских' authtoken' заголовка. Во-вторых: 'Access-Control-Allow-Headers: Content-Type, x-xsrf-token' ... Я не вижу, что вам разрешено отправлять свой собственный заголовок' authtoken'; это не в разрешенном списке. Вероятно, это проблема. – TheSharpieOne

+0

Я все равно должен был иметь заголовок 'Access-Control-Allow-Origin: x.x.x.x' (обычно IP-адрес), заданный в ответе. И это не может быть подстановочным знаком.Заголовок должен быть настроен, поскольку запросы будут отправляться из приложения. – schnauss

+0

'Access-Control-Allow-Origin' обычно не является IP-адресом, обычно это имена доменов ... если вы не обращаетесь к своему сайту через IP (в строке URL), это будут полностью квалифицированные имена доменов. '*' отлично работает для тестирования, вы бы хотели его заблокировать позже. Но это ни здесь, ни там ... не знаю, почему вы его подняли ... Я говорил о Access-Control-Allow - ** Headers **, который в настоящее время не позволяет вам отправлять заголовок 'authtoken' и блокирует ваш запрос, поскольку он не разрешен вашей конфигурацией. – TheSharpieOne

ответ

0

Я нашел решение, которое позволяет CakePHP обрабатывать CORS правильно preflights. Он устанавливает заголовки, отправляет ответ и выключает Cake до того, как запрошенное действие может работать.

Обязательно наличие во всех ваших контроллерах parent::beforeFilter();, чтобы этот код работал.

В AppController :: beforeFilter():

if($this->request->is("options")){ 
     // Set the headers 
     $this->response->header('Access-Control-Allow-Origin','*'); 
     $this->response->header('Access-Control-Allow-Methods','*'); 
     $this->response->header('Access-Control-Allow-Headers','Content-Type, Authorization'); 
     // Send the response 
     $this->response->send(); 
     // Don't do anything else! 
     $this->_stop(); 
    } 
+0

Возможно, вы захотите ознакомиться с [** диспетчерскими фильтрами **] (http://book.cakephp.org/2.0/en/development/dispatch-filters.html) и [** 'CakeResponse :: cors () '**] (http://api.cakephp.org/2.8/class-CakeResponse.html#_cors). – ndm

Смежные вопросы