IT忍者神龟之什么叫跨域访问
1.什么是跨域访问
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。 首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:
URL 说明 是否允许通信 http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同文件夹 允许 http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同端口 不允许 http://www.a.com/a.js https://www.a.com/b.js 同一域名,不同协议 不允许 http://www.a.com/a.js http://70.32.92.74/b.js 域名和域名对应ip 不允许 http://www.a.com/a.js http://script.a.com/b.js 主域相同,子域不同 不允许 http://www.a.com/a.js http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问) http://www.cnblogs.com/a.js http://www.a.com/b.js 不同域名 不允许
跨域的解决方案: 1.jsonp比较常用 2.CORS(Cross-Origin Resource Sharing)
JOSNP解决方案:
<script src=”http://www.example.net/api?param1=1¶m2=2″></script>
并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。
第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:
callback({“name”:”hax”,”gender”:”Male”})
这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。
跨域访问: 地址:http://p.3.cn/prices/mgets?skuIds=J_2146845&type=1&callback=setPrice 回调:setPrice 数据格式:[{"id":"J_2146845","p":"139.00","m":"159.00"}]
html代码: <button id="btn">按钮</button> <div id="div"></div>
js代码: var div = document. getElementById("div"); var oScript = null; var btn = document.getElementById("btn").onclick = function () { //伪造一个script加载过程 oScript = document.createElement("script"); oScript.src = "http://p.3.cn/prices/mgets?skuIds=J_2325379&type=1&callback=setPrice"; document.body.appendChild(oScript); }; function setPrice(str){ div.innerHTML = str[0].p; console.log(str[0].m); document.body.removeChild(oScript); }
cors解决方案:
这是一个W3C标准(显然比jsonp背景深厚许多),同样需要浏览器和服务器同时支持,但是整个通信过程,都是浏览器自动完成,不需要用户参与,就像平时写Ajax一样(如果使用的是jquery的话)。
下面是原生js实现CORS的代码
function createCORSRequest(method,url){
var xhr=new XMLHttpRequest();
if("withCredentials" in xhr){
xhr.open(method,url,true);
}else if(typeof XDomainRequest != "undefined"){//IE10之前的版本使用XDmainRequest支持CORS
xhr=new XDomainRequest();
xhr.open(method,url);
}else{
xhr=null;
}
return xhr;
}
var request=createCORSRequest("get","待访问的地址");
if(request){
request.onload=function(data){
//do sth
};
request.send();
}
适用场景:
承载的信息量大,get形式搞不定,需选用post传输。CORS支持所有类型的传输。
兼容性:
移动端全面支持(除opera mini),PC上IE8+。
CORS思想:
使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。(请求和响应都不包含cookie)
当然如果设置成下面这样,所有的跨域都可以实现了,但这样毕竟太不安全。
“Access-Control-Allow-Origin:*”;//允许任何域向我们的服务器发送请求
一般情况下,浏览器发送一个额外的Origin头部(由浏览器自动生成发送)
Origin:http://localhost:8080//本地网址
然后由服务器发送一个响应表头:Access-Control-Allow-Origin,如果服务器接收该请求,返回值(只能是通配符或单域名。)就和请求值一样。
Access-Control-Allow-Origin:http://localhost:8080
=>CORS方案的重点其实就在于服务器端的配置。
简单请求
- 只使用 GET, HEAD 或者 POST 请求方法。如果使用 POST 向服务器端传送数据,则数据类型(Content-Type)只能是 application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种。
- 不会使用自定义请求头(类似于 X-Modified 这种)。HTTP头部信息不超出以下{Accept,Accept-Language,Content-Language,Last-Event-ID,content-type(只限于上面提到的3种类型)}
对于简单请求,浏览器直接发出CORS请求。浏览器会自动在头信息(Request Headers)中,添加一个Origin 字段,来表明本次请求来自哪个域。
如果这个源不在许可范围内,会报错: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
如果Origin指定的域名在许可范围内(必须是跨域了的),Response Headers中会多出几个头信息字段。
Access-Control-Allow-Credentials:true//值为true表示允许发送cookie
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:http://localhost:8080
Access-Control-Max-Age:1728000
withCredentials属性
因为CORS默认不发送cookie和http认证,如果要把Cookie发到服务器,就要指定Access-Control-Allow-Credentials:true;
另外AJAX中也要打开withCredentials属性。
var xhr=new XMLHttpRequest();
xhr.withCredentials=true;
jquery ajax请求参数中加入
xhrFields: {
withCredentials: true
}
非简单请求
除了上面说的简单请求外都是非简单请求,比如:请求方法是PUT
或DELETE,或者Content-Type字段的类型是application/json,又或者有自定义请求头Access-Control-Request-Headers: X-Custom-Header。
比如,我添加自定义请求头
xhr.setRequestHeader('Some-Custom-Response-Header', 'value');
就会发现连续向同一地址请求了两次,而第一次请求什么值也没拿到
第二次请求
这是因为浏览器发现,这是一个非简单请求,就自动发出一个”预检”请求,要求服务器确认可以这样请求。”预检”请求用的请求方法是OPTIONS,表示这个请求是用来询问的。”预检”请求之后,浏览器球会进行正常CORS请求。
服务器端配置(rails为例)
1、可以参考这个方法:为 RESTful API 配置 CORS 实现跨域请求,写的挺详细的。然而对于rails并不算熟悉的我来说,有gem包,怎么可能放着不用呢~
2、这是Rack CORS 中间件的项目地址,按照文档的说明1分钟就可以基本搞
上一篇: 从MVC到前后端分离(附完整Demo)
下一篇: SpringBoot——静态资源映射规则
推荐阅读
-
asp.net core 系列之允许跨域访问2之测试跨域(Enable Cross-Origin Requests:CORS)
-
IT忍者神龟之什么叫跨域访问
-
SpringMVC之跨域访问
-
asp.net core 系列之允许跨域访问2之测试跨域(Enable Cross-Origin Requests:CORS)
-
什么是跨域访问?从前端和后端两个角度出发
-
怎么把使得用户访问abc.com的时候变为www.abc.com从而不跨域(cname、显性URL、隐性URL是什么意思)
-
怎么把使得用户访问abc.com的时候变为www.abc.com从而不跨域(cname、显性URL、隐性URL是什么意思)
-
什么是ajax跨域访问
-
JavaScript cookie 跨域访问之广告推广_javascript技巧
-
什么是跨域访问?从前端和后端两个角度出发