解决浏览器跨域限制发送ajax请求

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决浏览器跨域限制发送ajax请求相关的知识,希望对你有一定的参考价值。

一.什么是浏览器跨域限制?本质是什么?

所谓浏览器跨域限制,其实是为了数据安全的考虑由Netscape提出来限制浏览器跨域访问数据的策略,这是一中约定,正式叫法为浏览器同源策略,目前已经在大多数浏览器中支持。

本质上,所谓浏览器同源策略即:不允许浏览器访问跨域的Cookie,ajax请求跨域接口等。也就是说,凡是访问与自己不在相同域的数据或接口时,浏览器都是不允许的。 最常见的例子:对于前后端完全分离的Web项目,前端页面通过rest接口访问数据时,会出现如下问题:

  • 不允许发送POST请求:在发送POST请求之前会发送OPTIONS请求,HTTP响应状态码为403(Forbidden)。同时,在浏览器(firefox调试)控制台可以看到如下提示:
    已拦截跨源请求:同源策略禁止读取位于 http://host:port/path 的远程资源。(原因:CORS 头缺少 ‘Access-Control-Allow-Origin‘)。
  • 允许发送GET请求:HTTP响应状态码为200,但是不能读取服务器返回的数据。同时,在浏览器(firefox调试)控制台可以看到如下提示:
    已拦截跨源请求:同源策略禁止读取位于 http://host:port/path 的远程资源。(原因:CORS 头缺少 ‘Access-Control-Allow-Origin‘)。

对URL来说,所谓的“同源”包含3个要素:协议相同,主机(域名或IP地址,IP地址则看做是根域名)相同,端口相同。 举例来说,对于“http://test.chench.org/page.html”这个地址,以下情况被认为是同源与不同源的:

URL结果原因说明
http://test.chench.org/page2.html 同源 协议相同,主机相同,端口相同  
http://test.chench.org/dir2/page.html 同源 协议相同,主机相同,端口相同 相同域名下的不同目录
http://102.12.34.123/page.html 不同源 主机不同 域名与域名对应ip也不同源
http://test2.chench.org/page.html 不同源 主域名相同,子域名不同  
http://chench.org/page.html 不同源 域名不同 相同一级域名,不同二级域名
http://test.chench.org:81/page.html 不同源 端口不同 相同域名,不同端口
https://test.chench.org/page.html 不同源 协议不同 相同域名,不同协议
http://blog.icehoney.me/page.html 不同源 主机不同 不同域名

二.为什么会存在浏览器跨域限制?

既然目前各主流浏览器都存在跨域限制,那么为什么一定要存在这个限制呢?如果没有跨域限制会出现什么问题? 首先,浏览器同源策略的提出本来就是为了避免数据安全的问题,即:限制来自不同源的“document”或脚本,对当前“document”读取或设置某些属性。 如果没有这个限制,将会出现什么问题?不妨看一下几个情形:

  1. 可能 a.com 的一段 javascript 脚本,在 b.com 未曾加载此脚本时,也可以随意涂改 b.com 的页面(在浏览器的显示中)。
  2. 在浏览器中同时打开某电商网站(域名为b.com),同时在打开另一个网站(a.com),那么在a.com域名下的脚本可以读取b.com下的Cookie数据,如果Cookie中包含隐私数据,后果不堪设想。
  3. 因为可以随意读取任意域名下的Cookie数据,很容易发起CSRFg攻击。

所以,浏览器的同源策略是浏览器安全的基础,同源策略一旦出现漏洞被绕过,也将带来非常严重的后果,很多基于同源策略制定的安全方案都将失去效果。

三.对于浏览器来说,哪些资源(操作)会受到同源策略的限制?

对于浏览器来说,除了DOM,Cookie,XMLHttpRequest会受到同源策略的限制外,浏览器加载的一些第三方插件也有各自的同源策略。 最常见的一些插件如 Flash,Java Applet,Silverlight,Google Gears等都有自己的控制策略。 另外,存储在浏览器中的数据,如localStorage和IndexedDB,以源进行分割。每个源都拥有自己单独的存储空间,一个源中的Javascript脚本不能对属于其它源的数据进行读写操作。

四.浏览器跨域限制会带来什么问题?

随着互联网的发展,对用户体验的要求越来越高,AJAX应用也就越发频繁,AJAX的本质就是XMLHttpRequest。但XMLHttpRequest受到同源策略的约束,所以不能跨域访问资源。

五.解决浏览器跨域限制的方法有哪些?如何选择合适的方案?

1. JSONP

在浏览器中,<script><img><iframe><link>等标签都可以跨域加载资源,而不受同源策略的限制。这些带"src"属性的标签每次加载时,实际上是由浏览器发起了一次GET请求。不同于 XMLHttpRequest 的是,通过src属性加载的资源,浏览器限制了JavaScript的权限,使其不能读、写返回的内容。详细说明如下:

  • <script src="..."></script>标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。
  • <link rel="stylesheet" href="...">标签嵌入CSS。由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的Content-Type消息头。不同浏览器有不同的限制。
  • <img>嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG,...
  • <video><audio>嵌入多媒体资源。
  • <object>, <embed><applet>的插件。
  • @font-face引入的字体。一些浏览器允许跨域字体(ross-origin fonts),一些需要同源字体(same-origin fonts)。
  • <frame><iframe>载入的任何资源。站点可以使用X-Frame-Options消息头来阻止这种形式的跨域交互。

JSONP就是利用这个特性,可以加载对应的资源,间接绕开了浏览器同源策略的限制。 具体来说,就是在客户端通过动态创建javascript标签,并给标签设置src属性,在访问请求参数中传递需要回调的函数名;同时,服务端在响应jsonp请求时,将数据作为请求参数指定的客户端回调函数参数作为返回值,这样对于客户端来说服务器的响应数据其实是回调函数的参数,是javascipt对象,而不是字符串,因此避免了使用JSON.parse的步骤。

2. CORS(Cross-Origin Resource Sharing)

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。 具体来说,根据CORS标准定义,服务端需要在浏览器的跨域请求响应中包含指定消息头,浏览器根据响应消息决定是否可以访问跨域资源。

3. WebSocket

WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

4. 解决方法总结

方案优点缺点
jsonp 简单实用,老式浏览器全部支持,服务器改造非常小。 只支持GET请求,不支持POST等其他类型的HTTP请求,不能解决跨域页面之间的javasript调用问题
CORS W3C标准,是跨源AJAX请求的根本解决方法,允许任何类型的请求。  
WebSocket 不受浏览器同源策略影响 需要服务端支持协议,浏览器支持websocket,并非所有浏览器都支持websocket。

 

【参考】

 

以上是关于解决浏览器跨域限制发送ajax请求的主要内容,如果未能解决你的问题,请参考以下文章

Ajax 跨域解决——SpringBoot学习

ajax 跨域

跨域请求的解决方案

Ajax 跨域解决——SpringBoot学习

36SpringBoot配置Cors解决跨域请求

Ajax跨域