允许使用HTML5获取API的Access-Control-Allow-Origin标头


87

我正在使用HTML5提取API。

var request = new Request('https://davidwalsh.name/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

我能够使用普通的json,但无法获取上述api网址的数据。它引发错误:

提取API无法加载https://davidwalsh.name/demo/arsenal.json。请求的资源上不存在“ Access-Control-Allow-Origin”标头。因此,不允许访问源“ http:// localhost ”。如果不透明的响应满足您的需求,请将请求的模式设置为“ no-cors”,以在禁用CORS的情况下获取资源。


第三方服务器需要进行设置,您无法在客户端执行任何操作。
epascarello '16

@epascarello:我们可以在客户端进行。在后台,XHR请求正在进行。请检查此内容https://davidwalsh.name/fetch
iNikkz '16

Answers:


81

就像epascarello所说的那样,承载资源的服务器需要启用CORS。您可以在客户端执行的操作(可能是您正在考虑的操作)将获取模式设置为CORS(尽管我相信这是默认设置):

fetch(request, {mode: 'cors'});

但是,这仍然需要服务器也启用CORS,并允许您的域请求资源。

查阅CORS文档,以及有关Udacity的精彩视频,其中介绍了相同来源策略

您还可以在客户端使用no-cors模式,但这只会给您一个不透明的响应(您无法读取主体,但是响应仍可以由服务工作者缓存或由某些API占用,例如<img>) :

fetch(request, {mode: 'no-cors'})
.then(function(response) {
  console.log(response); 
}).catch(function(error) {  
  console.log('Request failed', error)  
});

2
您能否详细说明“但是仍然需要服务器同时启用CORS,并允许您的域请求资源”?我一直没有找到执行此操作的说明。
jayscript

2
@jayscript的整个过程如下所示:在客户端上,使用javascript提出了跨源请求。对于fetch API,“ cors”模式会告知浏览器可以提出此请求。如果您使用的是“ no-cors”模式,则浏览器将停止该请求,因为它与您的应用程序无关。服务器将收到请求并做出响应。该浏览器确认响应具有相应的CORS头,如果是这样,允许读取响应。如果标题不存在,浏览器将抛出错误。
David Scales

1
有关此MDN文章,请@jayscript进行详细介绍。本质上,您需要在服务器上设置以下标头:“ Access-Control-Allow-Origin:foo.example ”,“ Access-Control-Allow-Methods:POST,GET,OPTIONS”,“ Access-Control-Allow-Headers: X-PINGOTHER,内容类型”,分别启用来源,方法和标头。通常,“ *”用于来源标头。您还可以查看此Google文档和相关的代码实验室,以了解Fetch API:developers.google.com/web/ilt/pwa/working-with-the-fetch-api
David Scales

2
谢谢!这有助于我理解,当API服务器不包含任何标头时,就不可能从起源不同的API服务器中获取数据。在我正在处理的特殊情况下,我可以访问API服务器代码,并且可以自己添加标头,从而可以进行提取。
jayscript

这太蠢了,NO sendingCookie的安全问题是什么,因此允许CORS?
deathangel908

14

我的前端代码运行在http:// localhost:3000,而我的API(后端代码)运行在 http:// localhost:5000

正在使用提取API调用API。最初,它引发了“ cors”错误。然后在我的后端API代码中添加以下代码,从而允许从任何地方进行原始和标头。

let allowCrossDomain = function(req, res, next) {
  res.header('Access-Control-Allow-Origin', "*");
  res.header('Access-Control-Allow-Headers', "*");
  next();
}
app.use(allowCrossDomain);

但是,在其他环境(例如舞台,产品)的情况下,您应该限制您的出身。


20
这是一个可怕的答案。这是一个巨大的安全问题。如果您正在阅读本文,请不要这样做。
mjones.udri

1
这是针对本地设置的。例如,做一个快速的图片。是的,如果其他可部署环境也存在安全隐患。对于本地人,我感觉不是。“但是,在舞台,产品等其他环境下,您应该限制自己的出身”
smsivaprakaash

12

这为我工作:

npm install -g local-cors-proxy

我们要请求的具有CORS问题的API端点:

https://www.yourdomain.com/test/list

启动代理:

lcp --proxyUrl https://www.yourdomain.com

 Proxy Active 

 Proxy Url: http://www.yourdomain.com:28080
 Proxy Partial: proxy
 PORT: 8010

然后在您的客户端代码中,新的API端点:

http://localhost:8010/proxy/test/list

最终结果将是对https://www.yourdomain.ie/test/list的请求,而没有CORS问题!


请确保服务器正在并行运行,例如,打开新的cmt提示窗口并运行代码lcp --proxyUrl yourdomain.com
Govarthanan Venunathan

8

我知道这是一篇较旧的文章,但是我发现解决此错误的有效方法是使用服务器的IP地址,而不是在获取请求中使用域名。因此,例如:

#(original) var request = new Request('https://davidwalsh.name/demo/arsenal.json');
#use IP instead
var request = new Request('https://0.0.0.0/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

1

如果您使用的是nginx,请尝试

#Control-Allow-Origin access

    # Authorization headers aren't passed in CORS preflight (OPTIONS) calls. Always return a 200 for options.
    add_header Access-Control-Allow-Credentials "true" always;
    add_header Access-Control-Allow-Origin "https://URL-WHERE-ORIGIN-FROM-HERE " always;
    add_header Access-Control-Allow-Methods "GET,OPTIONS" always;
    add_header Access-Control-Allow-Headers "x-csrf-token,authorization,content-type,accept,origin,x-requested-with,access-control-allow-origin" always;

    if ($request_method = OPTIONS ) {
        return 200;
    }


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.