说到 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. T-SQL数据库备份

    /*1.--得到数据库的文件目录 @dbname 指定要取得目录的数据库名 如果指定的数据不存在,返回安装SQL时设置的默认数据目录 如果指定NULL,则返回默认的SQL备份目录名 */ /*--调用 ...

  2. 每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它

    mybatis – MyBatis 3 | 入门 http://www.mybatis.org/mybatis-3/zh/getting-started.html 作用域(Scope)和生命周期 理解 ...

  3. HTTP监视器charles入门使用教程分享---http/s packet monitors---ubuntu installation

    charles --usage http://www.cnblogs.com/chenlogin/p/5849471.html 按照Charles的提示,PC打开 chls.pro/ssl下载得到一个 ...

  4. jquery 获取对象

    jquery 获取对象 1.引用this作为对象时,必须以$(this)的形式变为对象目标,否则,无法识别,会报错“ has no method”

  5. JavaScript类库汇总

    日期处理Moment.js    http://momentjs.cn/  http://momentjs.com/ nodejslinq,jslinq    http://jslinq.codepl ...

  6. Linux下编译安装MySQL5.6

    [准备工作] 所有操作需要在root用户下 本机测试案例系统信息:centos7.3 安装路径:/usr/local/mysql [安装MySQL] 先安装如下依赖包: $ yum -y instal ...

  7. VS2010/MFC编程入门之二十二(常用控件:按钮控件Button、Radio Button和Check Box)

    言归正传,鸡啄米上一节中讲了编辑框的用法,本节继续讲解常用控件--按钮控件的使用. 按钮控件简介 按钮控件包括命令按钮(Button).单选按钮(Radio Button)和复选框(Check Box ...

  8. 推荐一个js脚本的字体拟合模型

    推荐一个js脚本的字体拟合模型 http://r3mi.github.io/poly2tri.js/   推荐一个js脚本的字体拟合模型 http://r3mi.github.io/poly2tri. ...

  9. EF Code First学习笔记:数据库创建(转)

    控制数据库的位置 默认情况下,数据库是创建在localhost\SQLEXPRESS服务器上,并且默认的数据库名为命名空间+context类名,例如我们前面的BreakAway.BreakAwayCo ...

  10. 浅谈JS严格模式

    浅谈JS严格模式 简介 何为严格模式?严格模式(strict mode)即在严格的条件下运行,在严格模式下,很多正常情况下不会报错的问题语句,将会报错并阻止运行. 但是,严格模式可以显著提高代码的健壮 ...