在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。然而,当进行一些比较深入的前端编程的时候,不可避免地需要进行跨域操作,这时候“同源策略”就显得过于苛刻。这时候就需要跨域!
同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
为什么要有同源限制
我们举例说明:比如一个黑客程序,他利用IFrame把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript读取到你的表单中input中的内容,这样用户名,密码就轻松到手了。而同源策略就为了防止这种事情发生。
比如说,浏览器的两个tab页中分别打开了 http://www.baidu.com/index.html和http : //www.google.com/index.html,其中,JavaScript1和JavaScript3是属于百度的脚本,而 JavaScript2是属于谷歌的脚本,当浏览器的tab1要运行一个脚本时,便会进行同源检查,只有和www.baidu.com同源的脚本才能被执行,所谓同源,就是指域名、协议、端口相同。所以,tab1只能执行JavaScript1和JavaScript3脚本,而JavaScript2不能 执行,从而防止其他网页对本网页的非法篡改。
如果两个页面拥有相同的协议(protocol),端口(如果指定),和主机,那么这两个页面就属于同一个源(origin)。
下图说明了同源策略的检测机制:
跨域网络访问
同源策略控制了不同源之间的交互,例如在使用 XMLHttpRequest
或标签时则会受到同源策略的约束。交互通常分为三类:
浏览器同源策略并不是对所有的请求均制约:
制约: XmlHttpRequest
不制约: img、iframe、script等具有src属性的标签
处理Ajax跨域问题主要有以下4种方式:
- 利用JSONP
- 利用iframe
- 利用代理
- 跨域资源共享(CORS)
JSONP
在 HTML DOM
中, script
标签是可以跨域访问服务器上的数据的.因此,可以指定 script
的 src
属性为跨域的 url
,从而实现跨域访问。
利用在页面中创建 <script>
节点的方法向不同域提交 HTTP
请求的方法称为 JSONP
,这项技术可以解决跨域提交 Ajax
请求的问题。
- 客户端代码:
function doResponse(data){ console.log('开始处理响应数据'); console.log(data); } //JSONP方式 $('#bt3').click(function(){ var script = document.createElement('script'); script.type = "text/javascript"; script.src="http://localhost/AJAX_day08/5.php?callback=doResponse"; document.head.appendChild(script); });
- 服务器端代码:
header('Content-Type: application/javascript'); $cb = $_REQUEST['callback']; $arr = ['ename'=>'King', 'age'=>50]; $str = json_encode($arr); echo $cb.'(' .$str. ')' ;
jQuery中两个可以发起JSONP请求的函数
$.getJSON()
XHR请求: $.getJSON('x.php', data, fn);
JSONP请求: $.getJSON('x.php?callback=?',data,fn);
$.ajax();
XHR请求:
$.ajax({ url: 'x.php', data: {'uname':'tom'}, success: fn })
JSONP请求:
$.ajax({ url: 'x.php', data: {'uname':'tom'}, dataType: 'jsonp', /*text/html/script/xml/json/jsonp指定服务器端返回的数据的类型*/ success: fn })
JSONP的优点
不像 XMLHttpRequest
对象实现的 Ajax
请求那样受到同源策略的限制;兼容性更好,在更加古老的浏览器中都可以运行,不需要 XMLHttpRequest
或 ActiveX
的支持;并且在请求完毕后可以通过调用 callback
的方式回传结果。
JSONP的缺点
只支持 GET
请求而不支持 POST
等其它类型的 HTTP
请求;它只支持跨域 HTTP
请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript
调用的问题。
iframe
一般分两种情况:
是同主域下面,不同子域之间的跨域
同主域,不同子域跨域,设置相同的document.domian就可以解决;
父页访问子页,可以document.getElementById(“myframe”).contentWindow.document来访问iframe页面的内容;如果支持contentDocument也可以直接document.getElementById(“myframe”).contentDocument访问子页面内容;
子页访问父页,可以parent.js全局属性;
不同主域跨域
前提, www.a.com
下 a.html
, a.html
内 iframe
调用了 www.b.com
下的 b.html
, b.html
下 iframe
调用了 www.a.com
下的 c.html
;
b.html
是不无法直接访问 a.html
的对象,因为涉及到跨域,但可以访问 parent
,同样 c.html
的 parent
可以访问 b.html
。 c.html
和 a.html
同域,是可以访问 a
下的对象的。 parent.parent.js
对象!
利用代理
即用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面(Post页面过去),由该页面代替用户页面完成交互,从而返回合适的结果。此方案可以解决现阶段所能够想到的多数跨域访问问题,但要求A网站提供Web代理的支持,因此A网站与B网站之间必须是紧密协作的,且每次交互过程,A网站的服务器负担增加,且无法代用户保存session状态。
跨域资源共享(CORS)
新版本的XMLHttpRequest对象,可以向不同域名的服务器发出HTTP请求。这叫做”跨域资源共享”(Cross-origin resource sharing,简称CORS)。
使用”跨域资源共享”的前提,是浏览器必须支持这个功能,而且服务器端必须同意这种”跨域”。如果能够满足上面的条件,则代码的写法与不跨域的请求完全一样。
服务器端则要进行一些设置:
header('Access-Control-Allow-Origin:*'); header('Access-Control-Allow-Methods:POST,GET');
结语
以上就是前端实现跨域的几种方式,很多时候我们都会遇到跨域的问题,以上几种方法就可以解决了,因此要好好掌握。
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。