zoukankan      html  css  js  c++  java
  • Spring MVC 实现跨域资源 CORS 请求

    说到 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.png

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

  • 相关阅读:
    [BJOI2019] 光线
    C# 从零开始写 SharpDx 应用 笔刷
    BAT 脚本判断当前系统是 x86 还是 x64 系统
    BAT 脚本判断当前系统是 x86 还是 x64 系统
    win2d 通过 CanvasActiveLayer 画出透明度和裁剪
    win2d 通过 CanvasActiveLayer 画出透明度和裁剪
    PowerShell 拿到显卡信息
    PowerShell 拿到显卡信息
    win10 uwp 如何使用DataTemplate
    win10 uwp 如何使用DataTemplate
  • 原文地址:https://www.cnblogs.com/linjiaxin/p/7992381.html
Copyright © 2011-2022 走看看