赞
踩
平时在开发中总是会遇到各种跨域问题,一直没有很好地了解其中的原理,以及其各种实现方案。今天在这好好总结一下。
本文完整的源代码请猛戳
xiangxingchen/bloggithub.com博客,建议大家动手敲敲代码。
一般来说,当一个请求url的协议、域名、端口三者之间任意一个与当前页面地址不同即为跨域。 之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。
为什么会有同源策略呢? 同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
同源策略限制内容有:
<script src="..."></script>
标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。<link rel="stylesheet" href="...">
标签嵌入CSS。由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的Content-Type
消息头。不同浏览器有不同的限制: IE, Firefox, Chrome, Safari
和 Opera
。<img>
嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG
<video>
和 <audio>
嵌入多媒体资源。<object>
, <embed>
和 <applet>
的插件。@font-face
引入的字体。一些浏览器允许跨域字体( cross-origin fonts)
,一些需要同源字体(same-origin fonts)
。<frame>
和<iframe>
载入的任何资源。站点可以使用X-Frame-Options
消息头来阻止这种形式的跨域交互。常见的跨域场景
- URL 说明 是否允许通信
- http://www.domain.com/a.js
- http://www.domain.com/b.js 同一域名,不同文件或路径 允许
- http://www.domain.com/lab/c.js
-
- http://www.domain.com:8000/a.js
- http://www.domain.com/b.js 同一域名,不同端口 不允许
-
- http://www.domain.com/a.js
- https://www.domain.com/b.js 同一域名,不同协议 不允许
-
- http://www.domain.com/a.js
- http://192.168.4.12/b.js 域名和域名对应相同ip 不允许
-
- http://www.domain.com/a.js
- http://x.domain.com/b.js 主域相同,子域不同 不允许
- http://domain.com/c.js
-
- http://www.domain1.com/a.js
- http://www.domain2.com/b.js 不同域名 不允许
注意:关于跨域,有两个误区: 1、动态请求就会有跨域的问题(错)。跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境 2、跨域就是请求发不出去了(错)。跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了
jsonp
的跨域原理是利用script
标签不受跨域限制而形成的一种方案。 下面我们来简单看一下代码实现
- <!-- index.html 文件 -->
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title></title>
- </head>
- <body>
- <script>
- var script = document.createElement('script');
- script.type = 'text/javascript';
-
- // 传参并指定回调执行函数为onBack
- script.src = 'http://127.0.0.1:3000/login?user=admin&callback=onBack';
- document.head.appendChild(script);
-
- // 回调执行函数
- function onBack(res) {
-
- alert(JSON.stringify(res));
- }
- </script>
- </body>
- </html>
node
- var qs = require('querystring');
- var http = require('http');
- var server = http.createServer();
-
- server.on('request', function(req, res) {
-
- console.log(req);
- var params = qs.parse(req.url.split('?')[1]);
- var fn = params.callback;
-
- // jsonp返回设置
- res.writeHead(200, {
- 'Content-Type': 'text/javascript' });
- res.write(fn + '(' + JSON.stringify(params) + ')');
-
- res.end();
- });
-
- server.listen('3000');
- console.log('Serv
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。