- A+
跨域,在平常工作中经常遇到,也经常被一些人问到跨域的处理方式。虽然处理跨域的几种方式都有用过,但是每次提到跨域的时候经常晕乎一下先,所以在这里总结一下平时用过的几种跨域方式。
1、通过jsonp跨域
在js中,我们直接用XMLHttpRequest请求不同域上的数据是不可以的,而在html中,能够实现跨域的就几种:
- link属性(css)
- href属性(a标签)
- src(img标签、script标签)
为了解决跨域的问题,结合script能够发起跨域请求的原理,产生了jsonp,即:动态的创建script标签,跨域的地址加上需要传送的数据和回调函数为script标签的src地址,执行完之后再动态的删除之前创建的script.
理解了原理之后,就很容易明白jsonp的缺点了:
- 只能用get方式请求,因为是使用src来传送数据
- 数据中出现中文需要编码。因为通过url传参数,可以在浏览器输入地址并带上中文参数试试
- src对请求的地址没有限制,会出现安全性的问题
2、document.domain
看到这个跨域方式,可能有些同学会觉得陌生,其实这个也很常用。
每次遇到有需要使用登录之类的项目,在开发的时候都需要将地址改成163的域名,为啥?在控制台打印一下document.domain试试,这篇文章的控制台输出的是feg.netease.com,而在有使用到163登录的项目中,输出的都是163.com。登录组件限制在163域名下才能用,但是163的域名有很多,避免不同域名之间出现通信问题,使用document.domain的方式将页面的主域名改成了163.com。这种方式主要用在主域名能设置成相同的页面之间的通信。如http://xyq.163.com/,它的主域名可以是xyq.163.com或163.com;http://xsd.163.com,它的主域名可以是xsd.163.com或163.com,所以这两个站点下的页面能够将主域名设置成163.com。
3、window.name的方式
这种方式利用了window对象name属性的特征:在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
使用window.name还需要使用iframe来实现,下面是页面和投票系统使用window.name方式实现的例子(投票地址:http://cgi.mmog.163.com:8088/v4a/show_vote/1250/):
页面的js:
var
_cdkey = $(
"#enter-cdkey .code-input"
).val(),
_urs = $(
"#enter-cdkey .mail-input"
).val(),
_phone = $(
"#enter-cdkey .phone-input"
).val();
var
_windowName = _urs +
"/"
+ _cdkey +
"/"
+ _phone;
var
_iframe = $(
"iframe"
);
_iframe.attr(
'src'
,
''
);
_iframe.attr(
'style'
,
'display:none'
);
_iframe.appendTo(
'body'
);
_iframe[0].contentWindow.name = _windowName;
_iframe.attr(
'src'
,
'http://cgi.mmog.163.com:8088/v4a/show_vote/1250/'
);
投票系统页面中处理window.name传过来的数据:
var
_urs = window.name.split(
'/'
)[0],
??
_cdkey = window.name.split(
'/'
)[1],
??
_phone = window.name.split(
'/'
)[2];
$(
'#voterinfo_10'
).val(_urs);
$(
'#voterinfo_70'
).val(_cdkey);
$(
'#voterinfo_41'
).val(_phone);
上面只是个简单的示例,大家有兴趣可以去尝试一下。
使用window.name方式对数据有一个限制:像上面例子示例的那样,数据是string。
4、Access-Control-Allow-Origin方式
正常情况下我们的接口都是jsonp的格式,可是万一遇到其它格式的接口怎么办?比如json格式,这个时候可以通过Access-Control-Allow-Origin来实现跨域。这种方式主要是后台同学配置,接口使用Access-Control-Allow-Origin设置对应项目的域名,前端同学这边像平常调用接口一样,不需要再做其他处理。如下面的例子:
$.ajax({
????
url:
"http://api.ypw.163.com/api/app"
,
????
type:
"POST"
,
????
data: JSON.stringify(postData),
????
dataType:
"application/json"
,
????
headers: {
"X-Ypw-Token"
: user_token,
"Content-Type"
:
"application/json"
},
????
success:
function
(result) {
????????
renderPage(result);
????
}
});
data为需要传输的数据,dataType是接口的格式。比平常接口调用多了的headers部分,是这个接口考虑到安全性的问题,接口开发同学需要我添加一个key,并且把user_token用base64加密之后传输给他,并不是跨域需要设置的东西,即这种方式跟平常调用接口一样。
好像这种方式挺好用的。确实,可是最大的问题是ie7、8、9都还不支持,所以目前也就能用在移动端了。
5、--allow-file-access-from-files --disable-web-security方式
这种方式是谷歌浏览器里面设置的,让浏览器允许跨域,如图
除了上面的设置方式之外,还可以通过cmd命令来启动,像平常用fis启动项目一样,先进入谷歌的安装路径,然后输入--allow-file-access-from-files命令来启动谷歌。之后在谷歌浏览器下则不需要考虑接口这些跨域的问题,像4中代码展示差不多,直接调用接口就可以了。
这种方式好像也很方便,但实际上平常开发的时候很少用到,因为除了限制在谷歌浏览器之外,即使是谷歌用户都不会去设置这个属性。我也是因为之前开发手游管理系统的时候用到了,因为最后系统上线的时候,整个系统都在一个服务器上,没有跨域的问题,但是开发过程中接口都放在各位开发同学的电脑上,开发过程中跨域了,所以使用了这种方式来处理。
- 我的微信
- 这是我的微信扫一扫
-
- 我的微信公众号
- 我的微信公众号扫一扫
-