详解 CORS跨域的几种不一样实现方式

CORS 定义

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing),它容许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。提供了 Web 服务从不一样域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不一样,CORS 除了 GET 要求方法之外也支持其余的 HTTP 要求。用 CORS 可让网页设计师用通常的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另外一方面,JSONP 能够在不支持 CORS 的老旧浏览器上运做。现代的浏览器都支持 CORS。html

CORS是W3c工做草案,它定义了在跨域访问资源时浏览器和服务器之间如何通讯。CORS背后的基本思想是使用自定义的HTTP头部容许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。W3C CORS 工做草案
同源策略:是浏览器最核心也最基本的安全功能;同源指的是:同协议,同域名和同端口。精髓:认为自任何站点装载的信赖内容是不安全的。当被浏览器半信半疑的脚本运行在沙箱时,它们应该只被容许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源;参考:JavaScript 的同源策略
JSON & JSONP:JSON 是一种基于文本的数据交换方式,或者叫作数据描述格式。JSONP是资料格式JSON的一种“使用模式”,可让网页从别的网域要资料,因为同源策略,通常来讲位于server1.example.com的网页没法与不是 server1.example.com的服务器沟通,而HTML的script元素是一个例外。利用script元素的这个开放策略,网页能够获得从其余来源动态产生的JSON资料,而这种使用模式就是所谓的JSONPjava

CORS 对比 JSONP

都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题nginx

  1. JSONP只能实现GET请求,而CORS支持全部类型的HTTP请求
  2. 使用CORS,开发者可使用普通的XMLHttpRequest发起请求和得到数据,比起JSONP有更好的错误处理
  3. JSONP主要被老的浏览器支持,它们每每不支持CORS,而绝大多数现代浏览器都已经支持了CORS

CORS,BROWSER支持状况

数据来源:caniuse.comgit

IE6,IE7,Opera min 不支持CORS。具体可参看数据来源中的 'show all'github

主要用途

  • From a browser script perspective: By allowing cross-domain requests, which are subject to tighter controls on the types of data that is exchanged. Cookies, for instance, are blocked unless specifically requested by the XHR author and allowed by the cross-domain web service. This is done to mitigate the risk of data leaks.
  • From a web service perspective: By utilising the origin URL reported by the browser the target cross-domain web service can determine, based on its origin policy, whether to allow or deny the request.
  • 从浏览器脚本的角度来看:经过容许跨域请求,对交换的数据类型进行更严格的控制。例如,除非XHR做者特别要求而且跨域Web服务容许,不然将阻止cookie。这样作是为了下降数据泄漏的风险。
  • 从Web服务的角度来看:经过使用浏览器报告的源URL,目标跨域Web服务能够根据其源策略肯定是否容许或拒绝请求。

Ajax请求跨域资源的异常

当出现以下异常时,那么就须要考虑跨域的问题了
例如 localhost:63343 经过Ajax请求http://192.168.10.61:8080服务器资源时就会出现以下异常:web

CORS 实现思路

CORS背后的基本思想是使用自定义的HTTP头部容许浏览器和服务器相互了解对方,从而决定请求或响应成功与否ajax

安全说明

CORS is not about providing server-side security. The Origin request header is produced by the browser and the server has no direct means to verify it.json

CORS 并非为了解决服务端安全问题,而是为了解决如何跨域调用资源。至于如何设计出 安全的开放API,倒是另外一个问题了,这里提下一些思路:跨域

  1. 请求时间有效性(验证timestamp与服务接到请求的时间相差是否在指定范围内,好比5分钟内)
  2. token验证
  3. ip验证
  4. 来源验证

例如浏览器

{

  'name': 用户名,

  ‘key: 加密的验证key,//(name+secret+timestamp来经过不可逆加密生成)

  ‘timestamp’: 时间戳,//验证timestamp与服务接到请求的时间相差是否在指定范围内,好比5分钟内

}

CORS 几种解决方案

CORS背后的基本思想是使用自定义的HTTP头部容许浏览器和服务器相互了解对方,从而决定请求或响应成功与否.

Access-Control-Allow-Origin:指定受权访问的域
Access-Control-Allow-Methods:受权请求的方法(GET, POST, PUT, DELETE,OPTIONS等)

一:简单的自定义CORSFilter / Interceptor

适合设置单一的(或所有)受权访问域,全部配置都是固定的,特简单。也没根据请求的类型作不一样的处理

在web.xml 中添加filter

<filter>

    <filter-name>cros</filter-name>

    <filter-class>cn.ifengkou.test.filter.CORSFilter</filter-class>

</filter>

<filter-mapping>

    <filter-name>cros</filter-name>

     <url-pattern>/*</url-pattern>

</filter-mapping>

新增CORSFilter 类

@Component

public class CORSFilter extends OncePerRequestFilter {

  @Override

  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

         throws ServletException, IOException {

      response.addHeader("Access-Control-Allow-Origin", "*");

      response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");

      response.addHeader("Access-Control-Allow-Headers", "Content-Type");

      response.addHeader("Access-Control-Max-Age", "1800");//30 min

      filterChain.doFilter(request, response);

     }

}

Access-Control-Allow-Origin只能配置 或者一个域名*
好比配置了192.168.56.130,那么只有192.168.56.130 能拿到数据,不然所有报403异常

response.addHeader("Access-Control-Allow-Origin", "http://192.168.56.130");

二:Nginx 配置支持Ajax跨域

这里是一个nginx启用COSR的参考配置:来源

#

# Wide-open CORS config for nginx

#

location / {

   if ($request_method = 'OPTIONS') {

     add_header 'Access-Control-Allow-Origin' '*';

     add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

       #

       # Custom headers and headers various browsers *should* be OK with but aren't

       #

       add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

       #

       # Tell client that this pre-flight info is valid for 20 days

       #

        add_header 'Access-Control-Max-Age' 1728000;

       add_header 'Content-Type' 'text/plain charset=UTF-8'; 

       add_header 'Content-Length' 0;

       return 204;

     }

   if ($request_method = 'POST') {

       add_header 'Access-Control-Allow-Origin' '*';

       add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

       add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

    }

   if ($request_method = 'GET') {

       add_header 'Access-Control-Allow-Origin' '*';

       add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

       add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

     }

}

三:支持多域名配置的CORS Filter

由于知道已经有能够用的库能够解决,因此就没重复造轮子了。其实由于懒,看看别人的源码算了。。。

mvnrepository搜索cors-filter,目前也就两个能够用

这两个也都大同小异,由于ebay开源在github上,也有详细的README,那么就以ebay的cors-filter为例

配置

添加依赖包到项目

<dependency>

    <groupId>org.ebaysf.web</groupId>

    <artifactId>cors-filter</artifactId>

    <version>1.0.1</version>

</dependency>

添加配置(具体配置项,仍是见项目的README.md吧)

<filter>

      <filter-name>CORS Filter</filter-name>

      <filter-class>org.ebaysf.web.cors.CORSFilter</filter-class>

      <init-param>

         <param-name>cors.allowed.origins</param-name>

         <param-value>http://192.168.56.129,http://192.168.56.130</param-value>

     </init-param>

     <init-param>

          <param-name>cors.allowed.methods</param-name>

         <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>

     </init-param>

     <init-param>

        <param-name>cors.allowed.headers</param-name>

        <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>

     </init-param>

 </filter>

 <filter-mapping>

     <filter-name>CORS Filter</filter-name>

     <url-pattern>/*</url-pattern>

</filter-mapping>

总结

    cors在开发WebService、RESTful API 时常常会遇到,在之前可能直接经过jsonp解决,jsonp怎么样就很少说了。 总之,CORS技术规范出来这么久了,若是不考虑IE6 IE7的问题,那么仍是积极拥抱CORS吧

    上文三种解决方案,经过搜索引擎均能找到,但估计大部分都是用的第一种最简单的无脑的Cors Filter处理,第二种方案是经过nginx配置的,并不适合全部Web应用。第三种,考虑得很周全,并且使用方便,若是不考虑造重复轮子,推荐使用。

本文转载自路径:http://www.cnblogs.com/sloong/p/cors.html

相关文章
相关标签/搜索