CORS-CakePHP不接受AngularJSON请求

CORS-CakePHP不接受AngularJSON请求,angularjs,cakephp,cors,cakephp-2.5,Angularjs,Cakephp,Cors,Cakephp 2.5,我使用CakePHP作为后端,AngularJS作为前端,而前端和后端在不同的域中,所以这基本上是一种CORS情况 基本上,我试图通过$http.post将表单的内容发送到Cake API(稍后这是用来进行身份验证的部分,但我之前失败了)。下面是代码: aeapBackend.login = function(username, password) { return $http.post( API_URL + 'api_mobile_user/login', {

我使用CakePHP作为后端,AngularJS作为前端,而前端和后端在不同的域中,所以这基本上是一种CORS情况

基本上,我试图通过
$http.post
将表单的内容发送到Cake API(稍后这是用来进行身份验证的部分,但我之前失败了)。下面是代码:

aeapBackend.login = function(username, password) {
    return $http.post(
        API_URL + 'api_mobile_user/login', {
            test: username,
            test2: password
        }
    );
};
而CakePHP中对应的API如下所示:

function beforeFilter() {
    parent::beforeFilter();
    $this->Auth->allow(array('login'));
}

public function login() {
    $this->response->header(array(
            'Access-Control-Allow-Origin' => '*',
            'Access-Control-Allow-Headers' => 'Content-Type'
        )
    );

    $this->autoRender = false;
}
接下来发生的事情是飞行前选项请求完成了——这对我来说非常好:

请求头:

OPTIONS /api_mobile_user/login HTTP/1.1
Host: aeap.localhost
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://asf.localhost
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53
Access-Control-Request-Headers: accept, content-type
Accept: */*
Referer: http://asf.localhost/?username_input=hjk&password_input=hjgk&login_button=
Accept-Encoding: gzip,deflate,sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
HTTP/1.1 200 OK
Date: Wed, 05 Nov 2014 15:29:00 GMT
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15
X-Powered-By: PHP/5.5.15
Set-Cookie: CAKEPHP=j6st0hnq8ear2cc6psg56d6eu3; expires=Wed, 05-Nov-2014 19:29:00 GMT; Max-Age=14400; path=/; HttpOnly
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
响应标题:

OPTIONS /api_mobile_user/login HTTP/1.1
Host: aeap.localhost
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://asf.localhost
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53
Access-Control-Request-Headers: accept, content-type
Accept: */*
Referer: http://asf.localhost/?username_input=hjk&password_input=hjgk&login_button=
Accept-Encoding: gzip,deflate,sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
HTTP/1.1 200 OK
Date: Wed, 05 Nov 2014 15:29:00 GMT
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15
X-Powered-By: PHP/5.5.15
Set-Cookie: CAKEPHP=j6st0hnq8ear2cc6psg56d6eu3; expires=Wed, 05-Nov-2014 19:29:00 GMT; Max-Age=14400; path=/; HttpOnly
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
但当实际的POST请求完成时,我得到一个状态代码403:

XMLHttpRequest cannot load http://aeap.localhost/api_mobile_user/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://asf.localhost' is therefore not allowed access. The response had HTTP status code 403. 
我怎样才能避免这种情况?在我看来,我已经为Cake['Access-Control-Allow-Origin']启用了CORS支持。在我看来,AngularJS发布了一些额外的信息,这些信息在飞行前没有被检查,然后被后端拒绝


使用过的版本:CakePHP 2.5.3,AngularJS:1.3.0

多亏了Marvin Smit,我能够确定未连接到CORS的行为的原因是标题。我在web服务器级别设置了
'Access-Control-Allow-Origin'=>'*'
,因此我能够得到一个指向CakePHP安全组件的响应

我基本上是试图向一个API发送一个POST Reuqest,而API并不希望数据被发布到它。因此,访问被拒绝。因此,我必须将
$this->Security->csrfCheck=false
添加到beforeFilter:

function beforeFilter() {
    parent::beforeFilter();
    $this->Auth->allow(array('login'));
    $this->Security->csrfCheck = false;
}

值得一提的是,对CakePHP3执行此操作的正确方法如下

public function beforeFilter() {
    parent::beforeFilter();
    $this->Auth->allow(array('login'));
    $this->eventManager()->off($this->Csrf);
}

尽管如此,对于AJAX请求不建议这样做。下面的文档可以为您提供更多帮助

我在CakePHP方面没有任何经验,但是只有当“选项”(飞行前)出现时,才能运行添加标题的服务器代码吗?另外,您要发送哪些标题?它们都在“默认HTTP头”列表中还是显式配置的“内容类型”?@MarvinSmit:“内容类型”已显式设置('Access-Control-Allow-headers'=>'content-type'),否则预飞行将失败。当我使用$http.get时,我从后端获取数据不会有任何困难,因此我假设头不只是在飞行前设置的。无论如何,谢谢你的评论——我会仔细检查一下。我对标题的意思是;一个好的CORS实现将返回一个401/403,如果发送的邮件中有一个不在“CORS的有效邮件头”列表中的邮件头。预飞行允许您查看是否允许使用实际POST发送头(使用“请求头”->由CORS实现用“允许的头”响应)。帖子中在“允许的标题”或“默认HTTP标题”(根据CORS规范)之外发送的任何标题都应导致“拒绝访问”。