前端如何跨域


在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请求的问题。

客户端代码:

1
2
3
4
5
6
7
8
9
10
11
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);
});

服务器端代码:

1
2
3
4
5
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请求:

1
2
3
4
5
$.ajax({
        url: 'x.php',
        data: {'uname':'tom'},
        success: fn
})

JSONP请求:

1
2
3
4
5
6
$.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)。
使用”跨域资源共享”的前提,是浏览器必须支持这个功能,而且服务器端必须同意这种”跨域”。如果能够满足上面的条件,则代码的写法与不跨域的请求完全一样。

服务器端则要进行一些设置:

1
2
header('Access-Control-Allow-Origin:*'); 
header('Access-Control-Allow-Methods:POST,GET');

结语

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

文章目錄
  1. 1. 同源策略
    1. 1.1. 为什么要有同源限制
  2. 2. 跨域网络访问
    1. 2.1. JSONP
      1. 2.1.1. 客户端代码:
      2. 2.1.2. 服务器端代码:
      3. 2.1.3. jQuery中两个可以发起JSONP请求的函数
    2. 2.2. iframe
      1. 2.2.1. 是同主域下面,不同子域之间的跨域
      2. 2.2.2. 不同主域跨域
    3. 2.3. 利用代理
    4. 2.4. 跨域资源共享(CORS)
  3. 3. 结语
|