为什么我会收到ERROR:“请求的资源上没有'Access-Control-Allow-Origin'标头”,尽管我指定了必要的标头?

时间:2018-02-06 14:50:48

标签: javascript node.js ajax cors

问题:

每当我向子域发出AJAX请求时,我都会收到错误。

错误告诉我请求的资源上没有“Access-Control-Allow-Origin”标题。

然而,我似乎在需要的地方指定了“Access-Control-Allow-Origin”?

我犯了什么错误,如何解决这个问题?

错误:

无法加载https://subdomain.example.com/endpoint:对预检请求的响应未通过访问控制检查:请求的资源上没有“Access-Control-Allow-Origin”标头。因此,不允许来源“https://www.example.com”。响应的HTTP状态代码为500。

CODE:

客户端

$.ajax({
        type: "POST",
        url: "https://subdomain.example.com/endpoint",
        data: theData,
        headers: {  
            'Access-Control-Allow-Origin': 'https://example.com',
            'Access-Control-Allow-Credentials': true
        },
        timeout: 600000,
        async: true,
        xhrFields: {withCredentials: true},
        crossDomain: true
    }).done(function(response) {

服务器

var whitelist = ['https://example.com'];

var corsOptions = {
    origin: function (origin, callback) {
        if (whitelist.indexOf(origin) !== -1) {
            callback(null, true)
        } else {
            callback(new Error('Not allowed by CORS'))
        }
    },
    credentials: true
}

router.options('/', cors(corsOptions), function(req,res,next){
    res.setHeader('Access-Control-Allow-Origin', 'https://example.com');
    res.status(200).end();
});

router.post("/", cors(corsOptions), function(req, res, next){

    res.setHeader('Access-Control-Allow-Origin', 'https://example.com');
    res.setHeader('Access-Control-Allow-Credentials', true);

 ...etc...

2 个答案:

答案 0 :(得分:0)

自从我使用node以来已经很长时间了,但只是查看代码,我认为您需要删除客户端请求中的标头。

然后确保在服务器响应中添加这些内容:

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

检查节点中的cors包是否已经执行此操作。

您在/< - 端点上发送标头,但在客户端中调用/ endpoint。最后一条路径可能没有设置任何访问控制头文件头。

要调试: 检查您的开发者控制台 - >网络,以查看正在访问的URL以及响应标头的内容。你应该看到这些访问控制标题。

如果您在那里看不到它们,则表示您的服务器端无法正常工作。

以下是一些很好的例子: CurrentFolderPane

并且确定一下:确保您从https://github.com/expressjs/cors调用API,因为https://example.com

答案 1 :(得分:0)

  

您可能错过了Vary标头。检查我的Vary标题部分。


说明

在客户端 - 服务器体系结构中,Access-Control-Allow-Origin是服务器端标头,通过它可以告诉浏览器是否允许它访问服务器上的资源。

Read this excellent mozilla documentation

在现代浏览器中,即使在客户端向服务器发出请求之前,浏览器也会发出预请求(a.k.a飞行前请求)以检查是否允许客户端向服务器发出请求。服务器应使用适当的标头响应浏览器以获取飞行前请求。作为响应,服务器必须发送Access-Control-Allow-Origin标头。如果您的主机名在服务器响应中返回,浏览器将允许您进行该呼叫,否则将阻止该呼叫。

很常见的情况是,服务器回复*作为Access-Control-Allow-Origin的值来指示浏览器每个人都可以拨打电话,但显然这不是一个好习惯,直到您打算制作服务器向公众开放。


Vary标题

根据文件,

  

如果服务器指定了源主机而不是" *",那么它还必须在Vary响应头中包含Origin,以向客户端指示服务器响应将根据Origin请求的值而不同报头中。

Access-Control-Allow-Origin: https://developer.mozilla.org
Vary: Origin


备注

此字段只能包含*或特定值。您不能使用逗号分隔值来允许多个主机。如果您想要允许多个主机(例如localhost用于本地测试,example.com用于生产),那么您可以轻松地在服务器端编写一些逻辑,如下所示:

let list = ['example.com', 'localhost']
if (request.headers.origin in list) {
    response.headers['Access-Control-Allow-Origin'] = request.headers.origin
}

以上PSEUDO-CODE基本上检查您的请求者是否在您允许的主机列表中,然后将该主机作为响应发送。