我正在尝试向 WCF 服务(我拥有的)发出跨域 HTTP 请求。我已经阅读了几种处理跨域脚本限制的技术。因为我的服务必须同时满足 GET 和 POST 请求,所以我无法实现一些动态脚本标记,其 src 是 GET 请求的 URL。由于我可以自由地在服务器上进行更改,因此我开始尝试实施一种解决方法,该解决方法涉及配置服务器响应以包含“Access-Control-Allow-Origin”标头和“预检”请求以及 OPTIONS 请求。我从这篇文章中得到了这个想法:Getting CORS working
在服务器端,我的 Web 方法是在 HTTP 响应中添加“Access-Control-Allow-Origin: *”。我可以看到响应现在确实包含此标头。我的问题是:我如何“预检”请求(选项)?我正在使用 jQuery.getJSON 发出 GET 请求,但浏览器立即取消了请求,并发出了臭名昭著的问题:
Access-Control-Allow-Origin 不允许来源 http://localhost
有人熟悉这种 CORS 技术吗?客户需要进行哪些更改才能预检我的请求?
谢谢!
在预检请求期间,您应该看到以下两个标头: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 响应标头。这个header的值应该和Access-Control-Request-Headers请求头中的headers一样,不能是'*'。
一旦您将此响应发送到预检请求,浏览器就会发出实际请求。您可以在此处了解有关 CORS 的更多信息:http://www.html5rocks.com/en/tutorials/cors/
尽管此线程可以追溯到 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;
,因为不需要预检。
通过这些简单的步骤在 Node.js 中编写自定义中间件来解决 CORS 问题。
don't need to set anything from the client, just a little change on the Node.js server will fix the problem.
创建中间件:
// in middleware/corsResolver.js
function corsResolver(req, res, next) {
// Website you wish to allow to connect
// running front-end application on port 3000
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
}
module.exports = corsResolver;
现在编辑你的 server.js(index.js 或任何启动你的节点服务器的主文件)并添加这个中间件:
// server.js or indes.js
const corsResolver = require('path/to/resolver-middleware')
app.use(corsResolver) // -----------> applied middleware here
// other stuff
CORS
预检的响应,因为它总是将这些标头添加到任何响应中。
Access-Control-Allow-Origin: *
//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(); });