Web
来源:互联网 发布:李安 知乎 编辑:程序博客网 时间:2024/06/03 20:25
跨域的产生是web安全的范畴,是浏览器安全里同源策略的部分,所谓同源策略,是指协议相同、
域名相同、端口相同,同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。1995年,同源政策由 Netscape 公司引入浏览器。
在这个策略下,web浏览器允许第一个页面的脚本访问第二个页面里的数据,但是也只有在两个页面有相同的源时。源是由URI,主机名,端口号组合而成的。这个策略可以阻止一个页面上的恶意脚本通过页面的DOM对象获得访问另一个页面上敏感信息的权限。
- http://www.app.com/categrory/other.html:同源
- http://app.com/categrory/other.html:不同源(域名不同)
- http://zy.www.app.com/categrory/other.html:不同源(域名不同)
- http://www.app.com:81/categrory/other.html:不同源(端口不同)
同源策略的交互图如下,主要是Origin的问题,所说的同源就是这个意思
有这种限制的主要原因就是如果没有同源策略将导致安全风险。假设用户在访问银行网站,并且没有登出。然后他又去了任意的其他网站,刚好这个网站有恶意的js代码,在后台请求银行网站的信息。因为用户目前仍然是银行站点的登陆状态,那么恶意代码就可以在银行站点做任意事情。例如,获取你的最近交易记录,创建一个新的交易等等。因为浏览器可以发送接收银行站点的session cookies,在银行站点域上。访问恶意站点的用户希望他访问的站点没有权限访问银行站点的cookie。当然确实是这样的,js不能直接获取银行站点的session cookie,但是他仍然可以向银行站点发送接收附带银行站点session cookie的请求,本质上就像一个正常用户访问银行站点一样。关于发送的新交易,甚至银行站点的CSRF(跨站请求伪造)防护都无能无力,因为脚本可以轻易的实现正常用户一样的行为。所以如果你需要session或者需要登陆时,所有网站都面临这个问题。如果上例中的银行站点只提供公开数据,你就不能触发任意东西,这样的就不会有危险了,这些就是同源策略防护的。当然,如果两个站点是同一个组织的或者彼此互相信任,那么就没有这种危险了。
当跨域的时候,浏览器的console如下图,Access-Control-Allow-Methods 报错,提示http请求跨域
目前,同源策略主要限制以下几类情况:
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
主要解决的途径:
jsonp(是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问)
<script type="text/javascript">$.ajax({ url:'http://app.huinonggroup.com/app', type:'POST', //GET async:true, //或false,是否异步 data:{ name:'yang',age:25 }, timeout:5000, //超时时间 dataType:'jsonp', //返回的数据格式:json/xml/html/script/jsonp/text jsonp:'callback', beforeSend:function(xhr){ console.log(xhr) console.log('发送前') }, success:function(data,textStatus,jqXHR){ console.log(data) console.log(textStatus) console.log(jqXHR) }, error:function(xhr,textStatus){ console.log('错误') console.log(xhr) console.log(textStatus) }, complete:function(){ console.log('结束') }});</script>
H5为了解决这个问题,引入了一个全新的API, 跨文档通信 API(Cross-document messaging)。
这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。
var popup = window.open('http://bbb.com', 'title');popup.postMessage('Hello World!', 'http://bbb.com');
postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即”协议 + 域名 + 端口”。也可以设为*,表示不限制域名,向所有窗口发送。
var win = document.getElementsByTagName('iframe')[0].contentWindow;var obj = { name: 'Jack' };// 存入对象win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://bbb.com');// 读取对象win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");window.onmessage = function(e) { if (e.origin != 'http://aaa.com') return; // "Jack" console.log(JSON.parse(e.data).name);};
服务端设置header头信息(* 可以指定域名访问权限)
// 指定允许其他域名访问 header('Access-Control-Allow-Origin:*'); // 响应类型 header('Access-Control-Allow-Methods:GET'); // 响应头设置 header('Access-Control-Allow-Headers:x-requested-with,content-type');
最后在说说P3P协议,P3P标准的构想是:Web 站点的隐私策略应该告之访问者该站点所收集的信息类型、信息将提供给哪些人、信息将被保留多少时间及其使用信息的方式,如站点应做诸如 “本网站将监测您所访问的页面以提高站点的使用率”或“本网站将尽可能为您提供更合适的广告”等申明。访问支持P3P网站的用户有权查看站点隐私报告,然 后决定是否接受cookie 或是否使用该网站。
//PHP使用P3P协议header( 'P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"' );
//JS使用P3P协议xmlhttp.setRequestHeader( "P3P" , 'CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"' );
谢谢你的阅读,希望对你有那么一点帮助。