什麼是跨域?和跨域的解決方案
一、跨域的由來
跨域大家都不陌生,跨域是為了克服瀏覽器的同源策略。但可能對瀏覽器為什麼會出同源策略有些陌生。這裡先簡單介紹跨域的由來。
瀏覽器的同源策略是為了限制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 大安全隱患之一。
2、CSRF可以做什麼?
你這可以這麼理解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支援
- 註解方式
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>