我正在构建一个Ionic1应用程序,它使用JSON Web Tokens (JWT)进行身份验证,与在CakePHP2.8中实现的rest api进行对话。
在未经授权的状态下,我的应用程序可以向服务器发出get/post请求,而不会出现问题。但是,一旦我通过了身份验证,并且我的应用程序在每次请求时都会发送一个authToken
头,Angular会首先自动发送一个OPTIONS
飞行前请求。
问题就从这里开始。由于自动飞行前请求没有设置authToken
头,并且由于api端点需要授权,cakephp用302 found重定向到/login
来响应。应用程序(或浏览器,在此测试阶段)认为这是不安全的,并且永远不会继续发出正确的请求。
我的问题是:如何让cakephp对飞行前选项请求做出适当的响应,以便angularjs知道它可以安全地向跨域服务器发送自定义头?
根据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
最佳答案
我找到了一个允许cakephp正确处理cors预飞的解决方案。它设置头,发送响应,并在请求的操作运行之前关闭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();
}