web前端跨域的一些解决方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web前端跨域的一些解决方案相关的知识,希望对你有一定的参考价值。

参考技术A

没有归纳之前对跨域的一些说法是模糊的,什么jsonp啊,跨域原理啊,心里只有一个大概的说法,知道这个东西,然后用的时候直接百度Ctrl+C,后来闲下来决定整理一波这些知识点,需知其所以然。

那么,其实这是浏览器对我们的一种保护机制,把坏人挡在门外。那么,问题来了,我们怎么确定门外的人到底是好人还是坏人呢?浏览器关上了坏人的一扇门,留给了我们好人一扇窗。

JSONP跟JSON没有关系..就好像javascript和Java一样
浏览器对script、img(这些标签的请求方式都是 GET ,所以jsonp不支持 POST )这种标签没有限制,我们就可以这样干

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

服务器端对于CORS的支持,主要就是通过设置 Access-Control-Allow-Origin 来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。 更多有关跨域资源共享 CORS 的知识

浏览器中可以查看对应的响应头,举个例子,如下

服务端允许CORS,服务端需要针对接口设置的一系列响应头 (Response Headers)

1.简单请求
目前大多数情况都采用这种方式。简单请求只需要设置 Access-Control-Allow-Origin 即可。满足以下两个条件,就属于简单请求。

2.非简单请求
非简单请求会发出一次预检测请求,返回码是204,预检测通过才会真正发出请求,这才返回200。来看栗子:

非简单请求需要根据不同情况配置不同的响应头,一系列响应头配置项见上方

这个说法相信不陌生,我们依然使用前端域名请求,然后有一个 中介商---代理 把这个请求转发到真正的后端域名上,那也就不存在跨域问题了。
比较普遍的nginx,简单的配置一下就可以了。了解更多的配置信息: nginx详解

然后前端这边的请求地址是 http://localhost:9099/api/xxx ,然后Nginx监听到地址是 localhost:9099/api 的请求,就帮我们转发到真正的服务端地址 http://baidu.com

CORS与JSONP的使用目的相同,但是比JSONP更强大。JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及在服务端同意jsonp方式时,可以向不支持CORS的网站请求数据。Nginx可以说是最方便的,不过需要部署Nginx才行,需要对服务器有一定的理解,不太适合刚入门的同学,当然也可以请后台同学帮忙部署。

window.postMessage(data,origin) 是 html5 的一个接口,专注实现不同窗口不同页面的跨域通讯。

现在是这么一个情况,由于同源策略的限制下, a.html 不能操作iframe( b.html )里面的dom,那么使用postMessage就可以解决这一情况

然后 b.html 页面通过message事件监听并接受消息:

这种方式只适合主域名相同,但子域名不同的iframe跨域。
比如主域名是 http://baidu.com/:8888 ,子域名是 http://child.baidu.com/:8888 ,这种情况下给两个页面设置相同的document.domain即document.domain = baidu.com 就可以访问各自的window对象了。

前端跨域整理
不要再问我跨域的问题了

前端跨域的解决方式

前端与服务端数据交互时,涉及到跨域的一些问题。JavaScript出于安全的考虑,禁止了跨域调用其他页面的对象,也即同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式。

什么是跨域?

如果两个页面拥有相同的协议(protocol),端口(如果指定),和主机,那么这两个页面就属于同一个源(origin),JavaScript允许这种同源页面的数据互相通信。

带来的麻烦,以及解决方案

同源策略让JavaScript或Cookie只能访问同域下的内容,但在实际开发项目时会不可避免的要进行跨域操作,因此给前端带来了麻烦,跨域能力也算是前端工程师的基本功之一,对于端口和协议的不同,只能通过后台来解决了,下面主要说说主机不同情况实现跨域。

神器JSONP

JSONP是比较流行的跨域处理方式,网络上的定义:JSONP是资料格式JSON的一种使用模式,可以让网页从别的网域要资料,原理是HTML的script标签可以加载并执行其他域JS文件。站点B把要提供的数据作为参数传给一个站点A定义的全局函数,站点A引用这个文件就可以跨域获取数据了,A站还可以把少量参数放在script标签的src里提交给B站。外链JS这种方案只支持GET,受IE下url长度不能超过2083个字节的限制和出于安全考虑,一般不用来提交数据。

JSONP实际上就是被包含在一个回调函数中的JSON,例如callback({"name":"zhangsan"});

因此我们可以知道JSONP有两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON数据,需要注意的是这个回调函数一定要让后端开发人员处理包裹,否则只能获取json数据,不能使用。

在js中,不可以直接用XMLHttpRequest请求不同域上的数据。但我们知道在页面上引入不同域上的js脚本文件是被允许的,JSONP就正是利用这个特性来实现的,例如:

<script src="http://jd.com/data.php?callback=dosomething"></script>

<script type="text/javascript">

function dosomething(jsondata){

  console.log(jsondata);

}

</script>

js文件载入成功后,会执行我们在url参数中指定的函数(dosomething),并且会把我们需要的json数据(jsondata)作为参数传入。所以再次强调jsonp是需要服务器端的页面进行相应的配合的。

<?php

  $callback=$_GET[‘callback‘];//得到回调函数名

  $data={‘name‘:‘张三‘,sex:‘男‘,age:‘15‘};//要返回的数据

  echo $callback.‘(‘.json_encode($data).‘)‘;//输出

?>

最终输出结果为:dosomething({‘name‘:‘张三‘,sex:‘男‘,age:‘15‘});

如果你使用jquery或者zepto,那么通过它封装的方法就能很方便的来进行JSONP操作了。

JSONP的优点是:

①:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制

②:它的兼容性更好,在老版本的浏览器中可以运行,不需要XMLHttpRequest或ActiveX的支持

③:它在请求完毕后可以通过调用callback的方式回传结果,方便调用。

JSONP的缺点则是:

①:它只支持GET请求而不支持POST等其他类型的HTTTP请求,不能提交大量数据

②:它只支持跨域HTTP请求这总情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

先进的CORS

W3C推荐了一种更为先进的机制,也就是CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部,让服务器能声明哪些来源可以通过浏览器访问该服务器上的资源,从而决定请求或响应是应该成功还是失败,CORS本身并非绝对很安全,可利用OAuth2措施来加强保障。

与JSONP相比较,CORS支持所有类型的HTTP请求,且开发者可以使用原生普通的XMLHttpRequest对象发起请求和获得数据,配合新的JSAPI一起使用,实现强大的新体验功能。

 

以上是关于web前端跨域的一些解决方案的主要内容,如果未能解决你的问题,请参考以下文章

前端跨域的解决方式

跨域的三种解决方式

前端解决跨域问题

前端跨域的方式

前端-关于CORS跨域的解决方案,面向服务端

前端跨域的三种解决方案