Access to XMLHttpRequest at ‘xxx’ from origin ‘xxx’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
有关跨域请求和同源策略的详细知识点见《同源策略及跨域解决方法》,这里只讲解Nginx服务器如何配置支持跨域请求,因为网上关于这个配置实在是五花八门,大家使用的请求方法、请求参数、请求参数格式以及是否会携带自定义头部等不同都会导致在Nginx上做不同的跨域请求配置,因此这篇文章不仅会讲解在Nginx上如何配置支持跨域请求,还会说说如何去定位…has been blocked by CORS policy…的出错点。
在《同源策略及跨域解决方法》中介绍过各个配置项的含义以及几个重要的概念“预检请求”、简单请求、非简单请求,会帮助我们理解这些配置项的含义。
注:下面的Nginx配置项都是放在location块中的
最简单的请求配上最简单的配置
如何请求是下面这样的,即简单请求,Nginx的配置也只需要简单的一个配置项即可,即允许跨域请求的源
$.ajax({
url:"http://xxx/1.php",
type:"post", //请求方式
dataType:"json", //解析后台响应的json格式
data:{"source":"hi"},
success: function(response){
console.log("成功");
console.log(response);
},
error: function(data) {
console.log("失败");
}
})
add_header Access-Control-Allow-Origin *;
非简单请求1
像下面这样,含有自定义头部Token,这样的请求变为非简单请求
$.ajax({
url:"http://xxx/1.php",
type:"post", //请求方式
dataType:"json", //解析后台响应的json格式
data:{"source":"hi"},
#如果是非简单请求,有些服务器需要需配置该项
#withCredentials:true,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader('Token', '123456789'); //自定义header头
},
success: function(response){
console.log("成功");
console.log(response);
},
error: function(data) {
console.log("失败");
}
})
if ($request_method = 'OPTIONS') {#如果是预检请求
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Max-Age 1728000; #预检请求保存的秒数
#这个配置项是关键,允许携带的请求头,上面的ajax请求头包含Token
add_header Access-Control-Allow-Headers Token;
return 204;
}
add_header Access-Control-Allow-Origin *;
非简单请求2
下面这样,请求方式为delete,则需要在Nginx中配置支持delete请求方式
$.ajax({
url:"http://xxx/1.php",
type:"delete", //请求方式
dataType:"json", //解析后台响应的json格式
data:{"source":"hi"},
success: function(response){
console.log("成功");
console.log(response);
},
error: function(data) {
console.log("失败");
}
})
if ($request_method = 'OPTIONS') {#如果是预检请求
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Max-Age 1728000; #预检请求保存的秒数
add_header Access-Control-Allow-Methods DELETE;
return 204;
}
add_header Access-Control-Allow-Origin *;
至此,如果你百度了很多方法都没解决为的话,不如仔细分析分析各个配置项的含义,以及发送的请求中有没有特殊请求头还未在服务器中进行配置,就像上面提到的服务器支持的请求方法,请求头。下面给出一个较完整的配置项:
//cors.conf
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Max-Age 1728000;
add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS,PUT,DELETE'; add_header Access-Control-Allow-Headers 'Token,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,ACCESS-TOKEN,x-file-name,Cookie';
add_header Content-Type 'application/json;application/x-www-form-urlencoded;text/plain; charset=utf-8';
add_header Content-Length 0 ;
add_header Access-Control-Allow-Credentials true;
return 204;
}
add_header Access-Control-Allow-Origin *;
#如果请求端需要获取除Content-Type之外的响应头,需要在这里设置
add_header Access-Control-Expose-Headers 'Connection,Content-Encoding';
//nginx.conf
location / {
include cors.conf;
root html;
index index.html;
}