CORS 预检请求返回“403 Forbidden”;随后的请求,然后仅在 Chrome 中发送
Posted
技术标签:
【中文标题】CORS 预检请求返回“403 Forbidden”;随后的请求,然后仅在 Chrome 中发送【英文标题】:CORS preflight request returning "403 Forbidden"; subsequent request then only sending in Chrome 【发布时间】:2013-04-15 14:09:57 【问题描述】:在this question 中使用pluploader 失败后,我现在正在尝试FineUploader。
阅读 CORS 后,我在我的 IIS6 服务器上实现了各种标头。
似乎发生的事情是我的脚本触发了第一个 (preflight
) 授权请求,但失败了,但 Chrome 允许第二个 (standard
) 请求发送 - Firefox 不允许。我认为这实际上是 Chrome 的一个错误,但至少它使我能够确定我的脚本可能正常工作。
这是在 Chrome 和 FF 中看到的第一个(预检)请求:
OPTIONS /frog/LOTS/upload/php.php HTTP/1.1
Host: staff.curriculum.local
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Origin: http://frogserver.curriculum.local
Access-Control-Request-Method: POST
Access-Control-Request-Headers: cache-control,x-requested-with
Pragma: no-cache
Cache-Control: no-cache
Access-Control...
标头是我添加到 IIS 中的标头。
这是我的响应标头:
HTTP/1.1 403 Forbidden
Content-Length: 1758
Content-Type: text/html
Server: Microsoft-IIS/6.0
x-powered-by: ASP.NET
Access-Control-Allow-Origin: http://frogserver.curriculum.local
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Cache-Control
Access-Control-Allow-Methods: OPTIONS, GET, POST
Access-Control-Expose-Headers: Origin, X-Requested-With
Date: Mon, 22 Apr 2013 15:19:20 GMT
我尝试并排比较这两者,但找不到任何会导致 preflight
请求返回 403 Forbidden
错误的标头。
我没有包含我的 PHP 源代码,因为它有很多代码。可以说它确实在 Chrome 中工作并且文件已正确上传,因此脚本应该是正确的。唯一值得一提的是,我的脚本开头有一个header("Content-Type: text/plain");
。将其更改为 text/html
对 Chrome 和 FireFox 没有任何影响。
javascript 非常简单:
$('#jquery-wrapped-fine-uploader').fineUploader(
request:
endpoint: 'http://staff.curriculum.local/frog/LOTS/upload/php.php'
,
cors:
expected: true, //all requests are expected to be cross-domain requests
sendCredentials: true //if you want cookies to be sent along with the request
);
有人可以帮忙吗?我今天在这个问题上花了 8 个小时,我 >
提前致谢,
【问题讨论】:
这对我来说真的不是一个 Fine Uploader 问题。您可能希望将其中一个标签更改为 IIS。 Fine Uploader 根本不涉及(很多)。用户代理发送 OPTIONS(预检)请求,而不是 Fine Uploader。出于某种原因,您的服务器以 403 拒绝此请求。您可能需要查看服务器日志以了解它为何以 403 响应。 再一次,为问得好问题+1! @RayNicholus 你是对的,这不是 Fine Uploader 的问题,但我认为说它不相关是错误的。 Fine Uploader 是否确定预检请求发送的标头? @dunc 不,Fine Uploader 不参与预检请求。它完全由用户代理处理。 好的@RayNicholus,谢谢。那么,您知道是什么决定了预检请求的标头吗? 【参考方案1】:我花了一个星期,但我终于找到了问题。
默认情况下,IIS6 不支持 .php 文件上的 OPTIONS 动词(或 .asp(x))。
因此,它根本无法识别 OPTIONS
预检调用。
要在 IIS6 中更改此值,请按以下步骤操作:
-
在 IIS 管理器中,转到您的根网站目录。右键单击它并选择“属性”
转到主目录选项卡,然后选择底部的“配置”按钮
找到您尝试与之通信的脚本的相关文件扩展名,例如 .php 或 .asp 并单击“编辑”
将
OPTIONS
添加到可用动词列表中(现在应该显示类似REQUEST, GET, POST, OPTIONS
的内容)
将以下代码添加到您的 PHP 脚本以确定来自 IE 的响应
如果我的 PHP 脚本中没有以下代码,我无法让 Internet Explorer 正常工作:
/* Is the request from Internet Explorer? */
if( !isset( $_SERVER['HTTP_X_REQUESTED_WITH'] )
|| ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] != "XMLHttpRequest" ) )
/* If so, we need to send a UUID and iframe XSS response script... */
header("Content-Type: text/html");
/* This needs some extra security, for sure */
if( $result["success"] == "true" )
$result["uuid"] = $_POST["qquuid"];
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
echo "<script src='iframe.xss.response-3.4.1.js'></script>";
else
/* Otherwise, we can just echo the json'd result */
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
我给了 Ray Nicholus 50 分的赏金,虽然我没有发现他的举止特别有帮助,但他一直都是对的。但是,出于其他人查看此帖子时遇到类似问题的目的,我会将我的答案标记为正确。
【讨论】:
是的,但是这个问题是重复的,正如我之前链接的那样:***.com/questions/6656354/… 只有 MSIE 10+ 支持 CORS,这就是它在 IE 中不起作用的原因......在那个版本之下,你只有一个功能非常有限的无用 XDomainRequest... 你发布了你的链接,看起来,当我写我的答案时.. :) 我相信你是对的,但是文件上传跨域现在可以在每个浏览器中使用 FineUploader ,所以我很高兴。 @inf3rno 此问题与您链接到的问题不同。 Fine Uploader 不使用 xhr 或 xdomain 请求在 ie9 或更早版本中上传文件。而是提交隐藏 iframe 内的表单。在尝试解析响应客户端时,消息传递用于解决跨域问题。这确实意味着 ie7 和更早版本不支持 cors 上传请求。【参考方案2】:正如我在 cmets 中提到的,这似乎是您的服务器的问题。出于某种原因,它拒绝了最初的 OPTIONS 请求。您将需要查看您的服务器日志,以了解您的服务器为何使用 403 响应此请求。
用户代理发送此初始 OPTIONS(飞行前)请求。 Fine Uploader 不直接发送这个请求,用户代理发送它是为了符合the CORS spec。如果您有关于 CORS 的具体问题,可以查看 my blog post 了解 Fine Uploader 如何处理 CORS,或/和阅读 this excellent MDN article on CORS。
【讨论】:
我已经阅读了您的博客和文章,但都没有帮助我解决这个问题。从我在浏览器的请求/响应中可以看到,预检请求应该可以工作 - 服务器允许标头和方法。 @dunc 您的服务器是否希望一些 cookie 与请求一起发送以对请求进行身份验证?如果是这样,这是你的问题。根据规范,预检请求不包括 cookie。 ...有关详细信息,请参阅w3.org/TR/cors/#cross-origin-request-with-preflight-0。 你好,雷。我尝试将sendCredentials
设置为 false
并从 IIS 中删除凭据标头,但得到的结果完全相同。
@dunc 听起来您似乎没有理解我的最后评论。让我重述一下。我的猜测是您的服务器期望凭据与选项请求一起发送。根据规范,这永远不会发生。这也许可以解释 403。以上是关于CORS 预检请求返回“403 Forbidden”;随后的请求,然后仅在 Chrome 中发送的主要内容,如果未能解决你的问题,请参考以下文章
如何修复对 etherpad 的 $http.get 请求上的“403(禁止)”
Django CORS 请求仅在服务器上创建 403 Forbidden Error
启用 CORS 和解决 403 Forbidden 错误的问题