《Nginx通过CORS实现跨域》要点: 本文介绍了Nginx通过CORS实现跨域,希望对您有用。如果有疑问,可以联系我们。
什么是CORS
CORS是一个W3C标准,全称是跨域资源共享(Cross-origin resource sharing).它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制.
当前几乎所有的浏览器(Internet Explorer 8+,Firefox 3.5+,Safari 4+和 Chrome 3+)都可通过名为跨域资源共享(Cross-Origin Resource Sharing)的协议支持AJAX跨域调用.
Chrome,Firefox,Opera,Safari都使用的是XMLHttpRequest2对象,IE使用XDomainRequest.
简单来说就是跨域的目标服务器要返回一系列的Headers,通过这些Headers来控制是否同意跨域.跨域资源共享(CORS)也是未来的跨域问题的标准解决方案.
CORS提供如下Headers,Request包和Response包中都有一部分.
HTTP Response Header
- Access-Control-Allow-Origin
- Access-Control-Allow-Credentials
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Expose-Headers
- Access-Control-Max-Age
HTTP Request Header
- Access-Control-Request-Method
- Access-Control-Request-Headers
其中最敏感的就是Access-Control-Allow-Origin这个Header,它是W3C标准里用来检查该跨域请求是否可以被通过.(Access Control Check).如果需要跨域,解决方法就是在资源的头中加入Access-Control-Allow-Origin 指定你授权的域.
启用CORS请求
假设您的应用已经在example.com上了,而您想要从www.example2.com提取数据.一般情况下,如果您尝试进行这种类型的AJAX调用,请求将会失败,而浏览器将会出现源不匹配的错误.利用CORS后只需www.example2.com 服务端添加一个HTTP Response头,就可以允许来自example.com的请求.
将Access-Control-Allow-Origin添加到某网站下或整个域中的单个资源
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Credentials: true (可选)
将允许任何域向您提交请求
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true (可选)
提交跨域请求
如果服务器端已启用了CORS,那么提交跨域请求就和普通的XMLHttpRequest请求没什么区别.例如现在example.com可以向www.example2.com提交请求.
var xhr = new XMLHttpRequest();
// xhr.withCredentials = true; //如果需要Cookie等
xhr.open('GET','http://www.example2.com/hello.json');
xhr.onload = function(e) {
?var data = JSON.parse(this.response);
?...
}
xhr.send();
服务端Nginx配置
要实现CORS跨域,服务端需要下图中这样一个流程
- 对于简单请求,如GET,只需要在HTTP Response后添加Access-Control-Allow-Origin.
- 对于非简单请求,比如POST、PUT、DELETE等,浏览器会分两次应答.第一次preflight(method: OPTIONS),主要验证来源是否合法,并返回允许的Header等.第二次才是真正的HTTP应答.所以服务器必须处理OPTIONS应答.
流程如下
- 首先查看http头部有无origin字段;
- 如果没有,或者不允许,直接当成普通请求处理,结束;
- 如果有并且是允许的,那么再看是否是preflight(method=OPTIONS);
- 如果是preflight,就返回Allow-Headers、Allow-Methods等,内容为空;
- 如果不是preflight,就返回Allow-Origin、Allow-Credentials等,并返回正常内容.
用伪代码表示
location /pub/(.+) {
? ?if ($http_origin ~ <允许的域(正则匹配)>) {
? ? ? ?add_header 'Access-Control-Allow-Origin' "$http_origin";
? ? ? ?add_header 'Access-Control-Allow-Credentials' "true";
? ? ? ?if ($request_method = "OPTIONS") {
? ? ? ? ? ?add_header 'Access-Control-Max-Age' 86400;
? ? ? ? ? ?add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,DELETE';
? ? ? ? ? ?add_header 'Access-Control-Allow-Headers' 'reqid,nid,host,x-real-ip,x-forwarded-ip,event-type,event-id,accept,content-type';
? ? ? ? ? ?add_header 'Content-Length' 0;
? ? ? ? ? ?add_header 'Content-Type' 'text/plain,charset=utf-8';
? ? ? ? ? ?return 204;
? ? ? ?}
? ?}
? ?# 正常nginx配置
? ?......
}
Nginx配置实例
实例一:允许example.com的应用在www.example2.com上跨域提取数据
在nginx.conf里找到server项,并在里面添加如下配置
location /{
add_header 'Access-Control-Allow-Origin' 'http://example.com';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Requested-With';
add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS';
...
}
如果需要允许来自任何域的访问,可以这样配置
add_header Access-Control-Allow-Origin *;
注释如下
第一条指令:授权从example.com的请求(必需)
第二条指令:当该标志为真时,响应于该请求是否可以被暴露(可选)
第三条指令:允许脚本访问的返回头(可选)
第四条指令:指定请求的方法,可以是GET,PUT,DELETE等(可选)
重启Nginx
$ service nginx reload
测试跨域请求
$ curl -I -X OPTIONS -H "Origin: http://example.com" http://www.example2.com
成功时,响应头是如下所示
HTTP/1.1 200 OK
Server: nginx
Access-Control-Allow-Origin: example.com
实例二:Nginx允许多个域名跨域访问
由于Access-Control-Allow-Origin参数只允许配置单个域名或者* ,当我们需要允许多个域名跨域访问时可以用以下几种方法来实现.
如需要允许用户请求来自www.example.com、m.example.com、wap.example.com访问www.example2.com域名时,返回头Access-Control-Allow-Origin,具体配置如下
(编辑:ASP站长网)
|