[聚合文章] 前端如何跨域

JSONP 2016-12-16 15 阅读

在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种方式:

  1. 利用JSONP
  2. 利用iframe
  3. 利用代理
  4. 跨域资源共享(CORS)

JSONP

HTML DOM 中, script 标签是可以跨域访问服务器上的数据的.因此,可以指定 scriptsrc 属性为跨域的 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 请求那样受到同源策略的限制;兼容性更好,在更加古老的浏览器中都可以运行,不需要 XMLHttpRequestActiveX 的支持;并且在请求完毕后可以通过调用 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.coma.htmla.htmliframe 调用了 www.b.com 下的 b.htmlb.htmliframe 调用了 www.a.com 下的 c.html ;

b.html 是不无法直接访问 a.html 的对象,因为涉及到跨域,但可以访问 parent ,同样 c.htmlparent 可以访问 b.htmlc.htmla.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');

结语

以上就是前端实现跨域的几种方式,很多时候我们都会遇到跨域的问题,以上几种方法就可以解决了,因此要好好掌握。

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。