一,概述
- 为什么会出现跨域问题
同源策略是浏览器安全的基石,首先由NetScape 公司引入浏览器,目前所有浏览器都实行这个政策。同源策略是一种约定,所谓同源策略,指的是浏览器对不同源的脚本或文本的访问进行限制,例如源A的js 不能读取和设置引入的源的元素属性。只有同协议 同域名 同端口 下才能访问。因为浏览器的同源策略的存在,才有了跨域问题。 - 同源策略的限制范围
(1)cookie,LocalStorage,和IndexDB 无法读取 (2)DOM 无法获得 (3)Ajax请求不能发送
- 没有同源策略限制的两大危险场景
(1)没有同源策略限制的接口请求:
cookie一般用来处理登录场景,目的是让服务器知道谁发的这次请求。如果你请求接口进行登录,服务端验证通过后会在响应头加入 Set-Cookie 字段,然后下次再发请求的时候,浏览器会自动将cookie 附加在HTTP请求的头字段Cookie中,服务端就知道这个用户已经登录过了。问题也就来了,如果你登录一个银行网站A,然后又进入一个非法网站B,如果没有同源策略,那么非法网站就会获取你登录A 网站的Cookie,这样一来不发网站就可以登录你A网站的账号为所欲为。这就是传说中的 CSRF攻击。(2)没有同源策略限制的DOM查询:
最常见的就是钓鱼网站。 有一天你收到一封邮件,说你的银行账户有风险,干净登录www.yinghang.com 进行修改,你打开界面发现和你以前登录的网站一模一样,然后你输入账户和密码登陆后发现账户余额正常,就离开了。可是你平时登录银行账户的网站是www.yinhang.com。这个钓鱼网站做了什么呢?
html <iframe></iframe> js var ifram = window.frames['yinhang']; var account = iframe.document.getElementById("你输入账户的输入框") var pwd = iframe.document.getElementById("你输入账户的密码框")
如果没有同源策略限制,你的账户和密码就会被非网站获取
二,跨域的解决方案(AJAX)
同源策略规定,AJAX请求只能发给同源的网址,否则就会报错。除了架设服务器代理
(浏览器请求同源服务器,后者再请求外部服务),有三种方法可以解决
- JSONP
- Websocket
- CORS
- JSONP
它的思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源策略限制。服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
首先,网页动态插入<script>元素,由它向跨源网址发出请求。
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://example.com/ip?callback=foo');
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
注意请求的查询字符串有一个callback参数,用来指定回调函数的名字,这是JSONP必须的,服务器收到请求后,会将数据放在回调函数的参数位置返回。
foo({
"ip":"192.168.1.159"
})
由于<script>元素请求的脚本,直接作为代码运行。这时只要浏览器定义了foo函数,该函数会被立即调用。
2.WebSocket
WebSocket 是一种通信协议,使用 ws://(非加密) 和 wss://(加密)作为协议前缀。该协议不实行同源策略,只要服务器支持,就可以通过它进行通信。
var ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = function (evt) {
console.log('Connection open ...');
ws.send('Hello WebSockets!');
};
ws.onmessage = function (evt) {
console.log('Received Message: ', evt.data);
ws.close();
};
ws.onclose = function (evt) {
console.log('Connection closed.');
};
3.CORS
CORS 是跨源资源分享(Cross-Origin Resource sharing) 的缩写,它是W3c标准,是跨域AJAX请求的根本解决办法。相比JSONP只能发GET请求,CORS允许任何类型的请求。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器(服务器端可是判断,让那些域可以请求)。只要服务器实现了CORS接口,
就可以跨源通信。