说到 AJAX 跨域,很多人最先想到的是 JSONP。的确,JSONP 我们已经十分熟悉,也使用了多年,从本质上讲,JSONP 的原理是给页面注入一个 <script>,把远程 JavaScript 放在页面上执行。这种做法会带来一个显而易见的问题:如果调用的来源被攻击或篡改,那什么东西都可以注入到页面里,造成 XSS 漏洞。另外,JSONP 本质上已经不是 XMLHttpRequest,所以在错误处理上也没有什么选择。而且 JSONP 只支持 GET 请求,所以 RESTful API 就没办法了。

这也就是为什么我们需要 CORS。CORS 是 Cross Origin Resource Sharing 的缩写,定义了浏览器和服务器间共享内容的新方式,通过它浏览器和服务器可以安全地进行跨域访问,它是 JSONP 的现代继任者。服务器上的 CORS 配置可以精细地指定允许跨域访问的条件:来源域、HTTP 方法、请求头、内容类型……等等。并且,CORS 让 XMLHttpRequest 也可以跨域,我们可以像往常一样编写 AJAX 调用代码。

所有现代浏览器都支持 CORS,所以你应该可以放心地使用它,只有在需要兼容老旧浏览器的场合,才用 JSONP 做 fallback。

支持 CORS 的浏览器在尝试进行跨域 XMLHttpRequest 时,会先发出一个“事前检查”,就是一个 OPTIONS请求,其中会包括一些有用的请求头:

Access-Controll-Request-Headers: accept, content-type
Access-Controll-Request-Method: POST

接着服务器会做出响应:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept
Access-Control-Max-Age: 1728000

最后浏览器会根据服务器的响应头,判断请求是否在服务器规定的范围内。比如来源是否在 Access-Control-Allow-Origin 里,HTTP 方法是不是在 Access-Control-Allow-Methods 里面,有没有不在 Allow-Headers 里面的请求头。如果以上条件都符合,那么浏览器就会放行这次请求,并且在 Access-Control-Max-Age 指定的时间内(单位是秒,以上设置的是 20 天)不需要再进行这种“事前检查”。

在以上服务器响应头中,Access-Control-Allow-Headers 不可以使用通配符。所以如果你要允许所有请求头,不妨把浏览器发来的 Access-Control-Request-Headers 直接返回。

事实上,如果跨域请求是“简单请求”,也就是 HTTP 方法为 GETHEADPOST,请求体的 MIME Type 是以下其中一种:application/x-www-form-urlencodedmultipart/form-data 或者 text/plain,并且没有自定义的请求头。这时浏览器只根据请求头中的 Origin 和服务器返回的 Access-Control-Allow-Origin 就可以判断了。但我们是 RESTful API,请求体是 application/json,所以只能用上面那种“事前检查”的方式。

另外,利用 CORS 还可以在跨域请求中发送 Cookie,这个特性是很有用的。只需要为 XMLHttpRequest 对象设置 withCredentials 属性:

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

但这种情况下,就不能指定 Access-Control-Allow-Origin: *,而是必须指定一个来源,比如 http://mydomain.com

下面来说说在服务器端怎么配置,以 springmvc框架为例。

什么是 CORS ?

跨来源资源共享(Cross-origin resource sharing)是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。
以上内容摘自维基百科

用人话来解释就是:JavaScript 或 Cookies 不允许访问不同域名下面的内容,当我们想在两个不同域名之前相互通信的话,我们就要考虑跨域这个问题,这也是在通往一个优秀的前端的路上必不可少的过程,如果你只会有 JSONP 的话,那真是令人伤感的,因为 JSONP 是不支持 POST请求的,所以,在科技发展的今天突然出现了 CORS 这项技术,好像就不需要前端什么事情了,我们可以帮他搞定跨域这个头疼的问题。其实是很简单的一项技术。

怎么使用呢?

据我所知道的是有三种方式:Tomcat 配置、拦截器设置响应头和使用 Spring MVC 4.2+

设置 Tomcat 这种方式就是引用别人封装好的两个 jar 包,配置一下web.xml就行了。我也并不推荐,这里放两个我在网上找到的配置相关文章,感兴趣可以看看。

  1. CORS Filter Installation
  2. tomcat下CORS(跨域资源共享) 的配置

拦截器设置响应头 这种方式原理就是利用拦截器在方法执行前,我们增加请求的响应头,用来支持跨域请求。这种方案是可行的,大部分都是采用这种方案。我当时也是打算采用这种方案,直到我发现原来 Spring 框架已经支持了 CORS 之后,就果断采用了 Spring 框架的内置的方案,其实原理也是一样的。

直接配置即可:

    <!-- API 接口跨域配置 -->
<mvc:cors>
<mvc:mapping path="/api/**"
allowed-origins="*"
allowed-methods="POST, GET, OPTIONS, DELETE, PUT"
allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
allow-credentials="true" />
</mvc:cors>

当然你也可以在Controller上使用 @CrossOrigin 注解。类似于这样:

到这里,支持 CORS 跨域请求就配置完成了,这里需要注意的地方是,你的Spring MVC 版本必须是 4.2 及以上
官方博客:CORS support in Spring Framework

Spring MVC 实现跨域资源 CORS 请求的更多相关文章

  1. 从零开始学 Java - Spring MVC 实现跨域资源 CORS 请求

    论职业的重要性 问:为什么所有家长都希望自己的孩子成为公务员? 答:体面.有权.有钱又悠闲. 问:为什么所有家长都希望自己的孩子成为律师或医生? 答:体面.有钱.有技能. 问:为什么所有家长都不怎么知 ...

  2. Java - Spring MVC 实现跨域资源 CORS 请求

    拦截器设置响应头 这种方式原理就是利用拦截器在方法执行前,我们增加请求的响应头,用来支持跨域请求.这种方案是可行的,大部分都是采用这种方案.我当时也是打算采用这种方案,直到我发现原来 Spring 框 ...

  3. spring mvc:ueditor跨域多图片上传失败解决方案

    公司在开发一个后台系统时需要使用百度的UEditor富文本编辑器,应用的场景如下: UEditor的所有图片.js等静态资源在一个专有的静态服务器上: 图片上传在另外一台服务器上: 因为公司内部会使用 ...

  4. Ajax+Spring MVC实现跨域请求(JSONP)(转)

    背景: AJAX向后台(springmvc)发送请求,报错:已阻止交叉源请求:同源策略不允许读取 http://127.0.0.1:8080/DevInfoWeb/getJsonp 上的远程资源.可 ...

  5. Ajax+Spring MVC实现跨域请求(JSONP)

    背景: AJAX向后台(springmvc)发送请求,报错:已阻止交叉源请求:同源策略不允许读取 http://127.0.0.1:8080/DevInfoWeb/getJsonp 上的远程资源.可 ...

  6. Ajax+Spring MVC实现跨域请求(JSONP)JSONP 跨域

    JSONP原理及实现 接下来,来实际模拟一个跨域请求的解决方案.后端为Spring MVC架构的,前端则通过Ajax进行跨域访问. 1.首先客户端需要注册一个callback(服务端通过该callba ...

  7. spring mvc的跨域解决方案

    什么是跨域 一句话:同一个ip.同一个网络协议.同一个端口,三者都满足就是同一个域,否则就是跨域. 为什么非得跨域 基于两个方面: a. web应用本身是部署在不同的服务器上 b.基于开发的角度 -- ...

  8. spring mvc 解决跨域问题

    Spring MVC 从4.2版本开始增加了对CORS的支持. 在Controller上使用@CrossOrigin注解: // 指定域名 @CrossOrigin("http://doma ...

  9. spring mvc支持跨域请求

    @WebFilter(urlPatterns = "/*", filterName = "corsFilter") public class CorsFilte ...

随机推荐

  1. Lucene.net的简单使用

    一.Lucene.net的简单介绍 1.为什么要使用Lucene.net       使用like的模糊查询,模糊度太低,中间添加几个字就无法查找.同时会造成数据库的全文检索,效率低下,数据库服务器造 ...

  2. redhat 6安装详解

    备注:redhat 6 系列OS安装步骤一致. 此处安装redhat 6.5 64位版本,即rhel-server-6.5-x86_64-dvd.iso 一.安装RHEL 6.5 用光盘成功引导系统, ...

  3. Convolution and polynomial multiplication

    https://www.mathworks.com/help/matlab/ref/conv.html?s_tid=gn_loc_drop conv Convolution and polynomia ...

  4. string unicode utf8 ascii in python and js

    http://www.jb51.net/article/62155.htm http://www.cnblogs.com/dkblog/archive/2011/03/02/1980644.html ...

  5. 对django框架架构和request/response处理流程的分析

    一. 处理过程的核心概念 如下图所示django的总览图,整体上把握以下django的组成: 核心在于中间件middleware,django所有的请求.返回都由中间件来完成. 中间件,就是处理HTT ...

  6. mysql 数据操作 多表查询 子查询 带比较运算符的子查询

    带比较运算符的子查询 #比较运算符:=.!=.>.>=.<.<=.<> #查询大于所有人平均年龄的员工名与年龄 思路 先拿到所有人的平均年龄然后 再用另外一条sql ...

  7. Shell特殊变量介绍与实践 $0

    2.$0特殊变量的作用及变量实践$0的作用为取出执行脚本的名称(包括路径) ,下面是该功能的实践.范例4-4:获取脚本的名称及路径. [root@salt-client- sh1]# cat n1.s ...

  8. 模仿Masonary写一个计算器

    1.CaculatorMaker @interface CaculatorMaker : NSObject @property(nonatomic,assign)int result; -(Cacul ...

  9. DrawLayout使用侧滑抽屉

    布局:fg_left_drawer <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...

  10. ffmpeg应用笔记

    官网 http://ffmpeg.org/ 应用手册 http://ffmpeg.org/documentation.html 雷霄骅专栏 https://blog.csdn.net/leixiaoh ...