1. 程式人生 > >什麼是跨域?和跨域的解決方案

什麼是跨域?和跨域的解決方案

一、跨域的由來

         跨域大家都不陌生,跨域是為了克服瀏覽器的同源策略。但可能對瀏覽器為什麼會出同源策略有些陌生。這裡先簡單介紹跨域的由來。

        瀏覽器的同源策略是為了限制CSRF攻擊,因為我們有些場景確實需要,訪問不同域名下的資源,所以需要跨域。所以就出現了各種跨域的方式,如JSONP、CORS、H5的postMessage、Nginx等方式,本文住要介紹JSONP和CORS。

二、CSRF

1、CSRF是什麼?

CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。它在 2007 年曾被列為網際網路 20 大安全隱患之一。

2CSRF可以做什麼?

        你這可以這麼理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義傳送惡意請求。CSRF能夠做的事情包括:以你名義傳送郵件,發訊息,盜取你的賬號,甚至於購買商品,虛擬貨幣轉賬......造成的問題包括:個人隱私洩露以及財產安全。

攻擊示例如下:

                            

3、模擬程式碼:

①、訪問網站A,首先使用者登入,程式碼如下

<form aciton="" method="post">
	<input type="text" name="account">
	<input type="password" name="password">
<form>

然後生成一個包含登入資訊的cookie

②、使用者可以在網站A轉賬:

<form method="post" id="form">
   <input type="text" name="money" id="money">//轉賬的金額
   <input type="text" name="receiver" id="receiver">//收款人
   <input type="submit" value="確認">
</form>

③、使用者訪問B網站,此時B網站Cookie沒有過期。

$(“#money”).val(100000);
$(“# receiver”).val(“黑客”);

$.ajax({
    type: "POST",
    cache: false,
    url:  "網站地址",
    data: $("form").serialize(),
    dataType: "json",
    success: function (data) {
      , error: function () {
    }
});	

這樣使用者A在不知情的情況下,錢丟了。

三、瀏覽器的同源策略

        為了防止CSRF攻擊,瀏覽器村的大佬們,想出了通過HTTP Referer驗證,是否是來自同一個網站。 同源包括要求協議相同、域名相同、埠相同。有任何一個不同則認為不同。

       現在大型網站中html、js、css、image等放置在不同的伺服器的需求。所以瀏覽器進行了一點妥協,img script style等標籤,都允許垮域引用資源,嚴格說這都是不符合同源要求的。

      JSON正是利用了瀏覽器的這點妥協而產生的。

四、JSOP介紹

       首先我們需要明白,在頁面上直接發起一個跨域的ajax請求是不可以的,但是,在頁面上引入不同域上的js指令碼卻是可以的,就像你可以在自己的頁面上使用<img src=""> 標籤來隨意顯示某個域上的圖片一樣。比如我在8080埠的頁面上請求一個9090埠的圖片:可以看到直接通過src跨域請求是可以的。

1、使用<script>標籤跨域:

①、localhost:8080  訪問獲取 localhost:9090 的資料 就屬於跨域。

②、script 跨域:

        當點選"跨域獲取資料"的按鈕時,新增一個<script>標籤,用於發起跨域請求;注意看請求地址後面帶了一個callback=showData的引數;

  showData即是回撥函式名稱,傳到後臺,用於包裹資料。資料返回到前端後,就是showData(result)的形式,因為是script指令碼,所以自動呼叫showData函式,而result就是showData的引數。

至此,我們算是跨域把資料請求回來了,但是比較麻煩,需要自己寫指令碼發起請求,然後寫個回撥函式處理資料,不是很方便。

程式碼如圖

                         

                         

2、使用jquery的jsonp方式跨域請求

        服務端程式碼不變,js程式碼如下:最簡單的方式,只需配置一個dataType:'jsonp',就可以發起一個跨域請求。jsonp指定伺服器返回的資料型別為jsonp格式,可以看發起的請求路徑,自動帶了一個callback=xxx,xxx是jquery隨機生成的一個回撥函式名稱。

        這裡的success就跟上面的showData一樣,如果有success函式則預設success()作為回撥函式。也可以自己指定函式,jsonpCallback: "showData" 。

                     

                    

問題:post不支援 Jsonp 為什麼?

總結:jQuery ajax方式以jsonp型別發起跨域請求,其原理跟<script>指令碼請求一樣,因此使用jsonp時也只能使用GET方式發起跨域請求。跨域請求需要服務端配合,設定callback,才能完成跨域請求。

五、CORS實現跨域

1什麼是CORS

    Cross-Origin Resource Sharing(CORS)跨來源資源共享是一份瀏覽器技術的規範,提供了 Web 服務從不同域傳來沙盒指令碼的方法,以避開瀏覽器的同源策略,是 JSONP 模式的現代版。

CORS是W3C工作草案,它定義了在跨域訪問資源時瀏覽器和伺服器之間如何通訊。

2、CORS 對比 JSONP

①、都能解決 Ajax直接請求普通檔案存在跨域無許可權訪問的問題

②、JSONP只能實現GET請求,而CORS支援所有型別的HTTP請求

③、使用CORS,開發者可以使用普通的XMLHttpRequest發起請求和獲得資料,比起JSONP有更好的錯誤處理

④、JSONP主要被老的瀏覽器支援,它們往往不支援CORS,而絕大多數現代瀏覽器都已經支援了CORS

3、CORS 實現思路

CORS背後的基本思想是使用自定義的HTTP頭部允許瀏覽器和伺服器相互瞭解對方,從而決定請求或響應成功與否

4、CORS 幾種解決方案

①:簡單的自定義CORSFilter / Interceptor

                       

②、有開源jar包支援

③、SpringMvc支援

  1. 註解方式

Controller類或其方法上加@CrossOrigin註解,來使之支援跨域。如下

            @CrossOrigin(origins = "*", maxAge = 3600)

            @CrossOrigin(origins="http://test.com",maxAge=3600)

        2) 配置檔案支援,在SpringMVC配置檔案中新增下面程式碼

<mvc:cors>
         <mvc:mapping path="/**" allowed-origins="*" allow-credentials="true"  max-age="1800" allowed-methods="GET,POST"/>

</mvc:cors>