1. 跨域的概念即什么情况下会发生跨域
一个网站的网址组成包括协议名,子域名,主域名,端口号。比如 https://github.com/ ,其中https是协议名,www是子域名,github是主域名,端口号是80,当在在页面中从一个url请求数据时,如果这个url的协议名、子域名、主域名、端口号任意一个有一个不同,就会产生跨域问题。
2. 跨域存在的形态
2.1 Ajax
不同域之间是数据传递
2.2 Cookie
访问不同域的cookie信息
2.3 Iframe
不在同一域的父子窗口的DOM操作
3. 如何处理跨域
3.1 Ajax:
3.1.1 Jsonp:客户端方法
- 原理:
在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。
Dosomething函数实现约定好
"http://xxx.xxx.xxx"为请求数据的地址
1 2 3 4 5 6 7 |
|
- 应用:
在实际应用中可以使用js动态的生成script标签来进行跨域
1 2 3 4 5 6 |
|
在使用jQuery的情况下可以使用$.getJSON方法,$.getJSON方法会自动判 断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步 加载js文件的形式来调用jsonp的回调函数。
1 2 3 4 5 |
|
或者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
- JSONP的优缺点:
JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题(用于传递数据)。
- 拓展:拥有src这个属性的标签都具有跨域的能力(img、script、iframe)
3.1.2 Cors(跨域资源共享):服务器端方法
- 原理:
CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。
- 应用:
服务器:
在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入以下内容即可:
Header set Access-Control-Allow-Origin *
PHP:
<?php header("Access-Control-Allow-Origin:*")>;*号表示允许任何域向我们的服务端提交请求;
也可以设置指定的域名,那么就只允许来自这个域名的请求
header("Access-Control-Allow-Origin: http://www.xxx.xx")
- 浏览器支持
3.2 Cookie
可使用ajax和iframe处理跨域的方式解决
3.3 Iframe
3.3.1 window.name实现跨域数据传输
- 原理:
一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
- 应用:
三个页面:
a.com/app.html:应用页面。
a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。
b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。
实现的步骤:
1.在应用页面中创建一个iframe,并把src指向数据页面;设置数据后再将iframe的src设置为与app.html同域的proxy.html。
Data.html:
1 2 3 |
|
app.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
3.3.2 利用iframe和location.hash
- 原理:
在url: a.com#helloword中的‘#helloworld’就是location.hash,改变hash并不会导致页面刷新,所以可以利用hash值来进行数据传递。
- 应用:与window.Name类似
app.htm页面通过iframe到data.htm中,由b.htm控制,看下图: 现在的关系为,app.htm中iframe加入了data.htm,data.htm页面中iframe加入了Proxy.html
Location.hash的应用与window.name类似:各页面主要操作如下
App.html:
var data = location.hash ? location.hash.substring(1) : '';
Proxy.html:
parent.parent.location.hash = window.location.hash//获取data传递过来的数据
data.html
parent.location.hash = 'somedata'
- 缺点:缺点是只支持string类型,大小受限制
3.3.3 document.domain实现跨子域
主域相同子域不同的页面,可以通过为两页面设置相同的document.domain来实现跨域,但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。
- 应用:
www.example.com/a.html中设置domain
1 2 3 4 5 6 |
|
example.com/b.html中设置domain
1 2 3 |
|
3.3.4 window.postMessage实现跨域
- 了解postmessage
otherWindow.postMessage(message, targetOrigin);
otherWindow: 要接收消息的那一个window对象
message: 所要发送的数据,string类型。
targetOrigin: 用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。
- 应用:
1 2 3 4 5 6 7 8 9 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
4. 跨域的安全问题
相关链接: