CORS-如何“预检” httprequest?


94

我正在尝试向WCF服务(我拥有)发出跨域HTTP请求。我已经阅读了几种处理跨域脚本限制的技术。因为我的服务必须同时容纳GET和POST请求,所以我无法实现某些动态脚本标签,其src是GET请求的URL。由于我可以自由地在服务器上进行更改,因此我开始尝试实现一种变通方法,该变通方法包括配置服务器响应以包括“ Access-Control-Allow-Origin”标头以及带有和OPTIONS请求的“预检”请求。我从这篇文章中得到了一个主意:让CORS工作

在服务器端,我的网络方法是在HTTP响应中添加“ Access-Control-Allow-Origin:*”。我可以看到响应现在确实包含此标头。我的问题是:如何“预检”请求(选项)?我正在使用jQuery.getJSON发出GET请求,但浏览器立即以臭名昭著地取消了该请求:

Access-Control-Allow-Origin不允许使用原始http:// localhost

有人熟悉这种CORS技术吗?客户需要对我的请求进行哪些更改?

谢谢!

Answers:


158

在预检请求期间,您应该看到以下两个标题:Access-Control-Request-Method和Access-Control-Request-Headers。这些请求标头向服务器询问发出实际请求的权限。您的飞行前响应需要确认这些标头,才能使实际请求生效。

例如,假设浏览器使用以下标头发出请求:

Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

然后,您的服务器应使用以下标头进行响应:

Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header

要特别注意Access-Control-Allow-Headers响应头。此标头的值应与Access-Control-Request-Headers请求标头中的标头相同,并且不能为“ *”。

一旦将此响应发送到预检请求,浏览器将发出实际请求。您可以在此处了解有关CORS的更多信息:http ://www.html5rocks.com/en/tutorials/cors/


您可以将多个域添加到Access-Control-Allow-Origin吗?
botbot

@botbot您现在可能已经解决了这个问题,但如果其他人想知道可以解决Access-Control-Allow-Origin: *
Steve Chambers

2
我可能错过了一些东西。那么我应该发送两个XMLHttp请求吗?一个用于预检;检查成功的响应,然后发送实际查询?
康坎2014年

14
@Kangkan,您无需担心发送预检请求。如果请求需要预检,浏览器将为您发送。
2014年

4
谢谢您的“特别关注”位...解决了我的node / expressjs问题,我能够添加一个过滤器来捕获这些飞行前请求//cors and preflight filtering app.all('*', function(req, res, next){.. //preflight needs to return exact request-header res.set('Access-Control-Allow-Headers', req.headers['access-control-request-headers']); if ('OPTIONS' == req.method) return res.send(204);next(); });
Kurtfm 2014年

0

尽管该主题可以追溯到2014年,但对于我们许多人来说,这个问题仍然是当前的。这是我在jQuery 1.12 / PHP 5.6上下文中的处理方式:

  • jQuery仅使用有限的标头发送了XHR请求;仅发送了“来源”。
  • 不需要飞行前要求。
  • 服务器只需要检测到这样的请求,并添加“ Access-Control-Allow-Origin:”。$ _SERVER ['HTTP_ORIGIN']标头,在检测到这是跨源XHR之后。

PHP代码示例:

if (!empty($_SERVER['HTTP_ORIGIN'])) {
    // Uh oh, this XHR comes from outer space...
    // Use this opportunity to filter out referers that shouldn't be allowed to see this request
    if (!preg_match('@\.partner\.domain\.net$@'))
        die("End of the road if you're not my business partner.");

    // otherwise oblige
    header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
}
else {
    // local request, no need to send a specific header for CORS
}

特别是,请勿添加,exit;因为不需要进行飞行前检查。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.