詳解 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

相關文章
相關標籤/搜索