Backbone & Slim PHP - Access-Control-Allow-Headers - 可以获取信息,不能发布吗?

Posted

技术标签:

【中文标题】Backbone & Slim PHP - Access-Control-Allow-Headers - 可以获取信息,不能发布吗?【英文标题】:Backbone & Slim PHP - Access-Control-Allow-Headers - Can GET information, can't POST it? 【发布时间】:2012-10-28 21:25:09 【问题描述】:

我正在使用 Backbone 和 Slim php 框架。我正在尝试将信息发布到我的 API,但是 Access-Control-Allow-Headers 不断给我带来问题...

我的控制台显示:

    OPTIONS http://api.barholla.com/user/auth 405 (Method Not Allowed) zepto.min.js:2
XMLHttpRequest cannot load http://api.barholla.com/user/auth. Request header field Content-Type is not allowed by Access-Control-Allow-Headers.

我的标题是:

Request URL:http://api.barholla.com/user/auth
Request Method:OPTIONS
Status Code:405 Method Not Allowed
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, content-type, accept
Access-Control-Request-Method:POST
Connection:keep-alive
Host:api.barholla.com
Origin:http://localhost
Referer:http://localhost/barholla/app/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (Khtml, like Gecko) Chrome/22.0.1229.94 Safari/537.4
Response Headersview source
Access-Control-Allow-Origin:*
Allow:POST
Connection:close
Content-Type:application/json
Date:Thu, 08 Nov 2012 16:12:32 GMT
Server:Apache
Transfer-Encoding:chunked
X-Powered-By:Slim
X-Powered-By:PleskLin

我的精简 index.php 文件中的标题是:

$res = $app->response();
$res->header('Access-Control-Allow-Origin', '*');
$res->header("Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS");

处理帖子数据:

$app->post('/user/auth', function () use ($app) 
//code here
);

在我的 javascript(我正在使用主干框架)中,我的代码是:

 App.userAuth = new App.UserAuthModel(
  username: $('#username').val(),
  password: hex_md5($('#password').val())
);

App.userAuth.save(, 
  success: function(model, resp) 
    console.log(resp);
  ,
  error: function(model, response) 
    console.log(response);
  
);

任何帮助将不胜感激,我已经坚持了很长时间!

【问题讨论】:

【参考方案1】:

我有一个类似的跨域POST 问题(实际上除了GET 之外的所有标题)。以下解决了它:

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && (   
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST' || 
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'DELETE' || 
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'PUT' )) 
             header('Access-Control-Allow-Origin: *');
             header("Access-Control-Allow-Credentials: true"); 
             header('Access-Control-Allow-Headers: X-Requested-With');
             header('Access-Control-Allow-Headers: Content-Type');
             header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT'); // http://***.com/a/7605119/578667
             header('Access-Control-Max-Age: 86400'); 
      
  exit;

【讨论】:

完美解决方案【参考方案2】:

在您的 javascript 客户端中,您正在向 /user/auth 发出 OPTIONS 请求,但在您的 PHP 代码中,您只接受通过此端点的 POST 请求。

如果您希望您的 API 接受 OPTIONS 方法,您的代码中应该有这样的内容:

$app->options('/user/auth', function () use ($app) 
    //code here
);

或者,如果您想在同一个函数中处理多个 HTTP 方法:

$app->map('/user/auth', function () use ($app) 
    if ($app->request()->isOptions()) 
        //handle options method
    

    else if ($app->request()->isPost()) 
        //handle post method
    
)->via('POST', 'OPTIONS');

请记住,OPTIONS 方法 according to W3C:

[...] 表示请求有关在由 Request-URI 标识的请求/响应链上可用的通信选项的信息的请求。此方法允许客户端确定与资源相关的选项和/或要求,或服务器的功能,而无需暗示资源操作或启动资源检索。

或者,只需更改客户端的代码以发出 POST 请求而不是 OPTIONS 请求。它比通过 OPTIONS 方法验证用户更容易也更有意义。在 zepto.js 中会是这样的:

$.post('/user/auth',  foo: 'bar' , function(response) 
    console.log(response);
);

【讨论】:

【参考方案3】:

您的 OPTIONS 请求应该是 200,返回一个空响应。然后浏览器会发送真正的 POST 请求。

也无需在Access-Control-Allow-Methods 标头中添加 OPTIONS。

看来你在使用身份验证,为什么不添加Access-Control-Allow-Credentials 标头呢。

有关更多信息,请查看此code,它可能会有所帮助。

【讨论】:

【参考方案4】:

CorsSlim 帮助了我。 https://github.com/palanik/CorsSlim

<?php 
$app = new \Slim\Slim();
$corsOptions = array("origin" => "*",
"exposeHeaders" => array("Content-Type", "X-Requested-With", "X-authentication", "X-client"),
"allowMethods" => array('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'));
$cors = new \CorsSlim\CorsSlim($corsOptions);
$app->add($cors);

【讨论】:

以上是关于Backbone & Slim PHP - Access-Control-Allow-Headers - 可以获取信息,不能发布吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Backbone Js 和 SLIM 框架进行用户身份验证

html 上传Backbone Slim Framework http://www.ebizdesigner.com/item/52-backbonejs-mvc-app-tea-tree-part-

PHP Slim 解码 JWT 令牌

UVa 1395 - Slim Span(最小生成树变形)

Backbone UI 和 CMS 后端:涉足 Restful CRUD

如何手动安装php slim?