同源策略:
1.源:由协议,域名,端口号组合而成。
2,同源:即地址中的协议,域名和端口号均相同。
3.同源策略:同源策略是浏览器的一个安全功能,不同源的客户端在没有明确授权的情况下,不能读写对方的资源。
4.不同源:地址中的协议,域名或者端口,任意一个不同,都称其不同源。
5.受到同源限制:
- 无法读取不同的Cookie,localStroage和indexDB.
- 无法获取不同源的DOM.
- 不能向不同源的服务器发送ajax请求。
6.不受同源限制:
- 页面中的链接,重定向以及表单提交是不会受到同源策略的限制。
- 在浏览器中,
跨域
What:
跨域问题,就是受同源策略的影响,不是同源的脚本不能操作其它源下的对象。想要操作另一个源下的脚本,就需要跨域。
How:
1. 降域:document.damain。如:
son1.a.com与a.com
son1.a.com与son2.a.com
child.son1.a.com与 son1.a.com
两两不同源,可以通过设置document.damain='a.com',
浏览器就会认为它们都是同一个源。想要实现两个页面之间的任意通信,两页面均要设置document.damain='a.com'.
此方式的特点:
- 只能在父域名和子域名之间使用,且将
child.son1.a.com
设置成a.com
之后,就不能再设置成son1.a.com
。 - 存在安全问题,当一个站点被攻击,另一个站点就会引起安全漏洞。
- 使用的局限性,只适用于Cookie和iFrame窗口。
2.JSONP跨域
JSONP和JSON没有任何关系!
JSONP原理:(举例:a.com/jsonp.html想得到b.com/main.js中的数据)。在a.com的jsonp.html里创建一个回调函数XXX,动态添加<script>
元素,向服务器发送请求,请求地址后面加上查询字符串,通过callback参数指定回调函数的名字。请求地址为http://b.com/main.js?callback=xxx
。在main.js中调用这个回调函数XXX,并以JSONP数据形式作为参数传递,完成回调。
// a.com/jsonp,html中的代码:
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://b.com/main.js?callback=foo');
} //window.onload是为了让页面加载完成后再执行
function foo(data) {
console.log(data.name+"欢迎您");
};
//b.com/main.js中的代码:foo({name:"hi})
这样就实现了跨域的参数传递。
采用jsonp跨域存在的问题:
1.使用此方法,每个网站都可以拿到数据,存在安全性问题。需要网站双方商议基础的token身份验证。
2.只能是get,不能是post.
3.可能被注入恶意代码,篡改页面内容,可以采用字符串过滤来规避此问题。
3.CORS
CORS是一个W3C标准,全称是:跨域资源共享。它允许浏览器向资源服务器发出XMLHttpRequest请求,从而客服AJAX只能同源使用的限制。
在刚才的例子中,在b.coml里面添加响应头声明允许a.com的访问代码Access-Control-Allow-Origin: http://a.com
然后a.com就可以用ajax获取b.com里的数据了。
4.window.name跨域
浏览器窗口有window.name属性。这个属性的特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属性,后一个网页可以读取它。比如,你在b页面里设定
window.name="hello"
你在返回到a页面的时候,访问window.name
,可以得到hello
.
eg:现在浏览器的一个标签页里打开http://www.damonare.cn/a.html
页面,你通过location.href=http://baidu.com/b.html
,在同一个浏览器标签页里打开了不同域名下的页面。这时候这两个页面你可以使用window.name
来传递参数。因为window.name
指的是浏览器窗口的名字,只要浏览器窗口相同,那么无论在哪个网页里访问值都是一样的。
特点:window.name容量很大,可以放置非常长的字符串;但是必须监听子窗口window.name属性的变化,影响网页性能。
5.postMessage方法跨域
HTML5中引入了一个全新的API,跨文档通信的API。这个API为window对象新增了一个
window.postMessage
方法,允许跨窗口通信,不论这两个窗口是否同源。a可以把它的LocalStorage,发送给b,b也可以把自己的LocalStorage发送给a.
- window.postMessage(message, targetOrigin, [transfer]),有三个参数
- message,向目标窗口发送的数据;
- targetOrgin,来指定哪些窗口能接收到消息事件,可以是一个URL(发送消息的目标域名)。
3.transfer可选参数,是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
- 接受消息放必须有监听事件,负责发送消息时就会报错。
window.addEventListener("message",onmessage)onmessage
eg:在a页面执行
var popup = window.open('http://localhost:3000', 'title');
popup.postMessage('Hello World!', 'http://localhost:3000');
同时在http://localhost:3000
的页面里监听message事件。
window.onload=function () {
window.addEventListener("message",onmessage);
}
function onmessage(event) {
if(event.origin=="http://localhost:63343"){//http://localhost:63343是发送方a的域名
console.log(event.data);//'Hello World!'
}
console.log(event.data);//'Hello World!'
}
6.location.hash跨域
location.hash就是指URL的#后面的部分。
父窗口改变子窗口的Url的#号后面的部分,后者把要传递的参数写在#后面,子窗口监听
window.onhashchange
事件,读取window.location.hash
解析出有用的数据。子窗口也可以向父窗口传递数据。