一、什麼是JS跨域
1、跨域:在瞭解跨域之前,首先要知道什麼是同源策略(same-origin policy)。簡單來講同源策略就是瀏覽器爲了保證用戶信息的安全,防止惡意的網站竊取數據,禁止不同域之間的JS進行交互。對於瀏覽器而言只要域名、協議、端口其中一個不同就會引發同源策略,從而限制他們之間如下的交互行爲:
2、JS跨域:指通過js在不同的域之間進行數據傳輸或通信,比如用ajax向一個不同的域請求數據,或者通過js獲取頁面中不同域的框架中(iframe)的數據。
那什麼是不同的域呢?只要協議、域名、端口有任何一個不同,都被當作是不同的域。
舉例:
域名 | 說明 | 是否允許訪問 |
http://www.example.com | 協議不同 | 不允許訪問 |
https://www.example.com | ||
http://www.example.com:8080 | 端口不同 | 不允許訪問 |
http://www.example.com:3306 | ||
http://www.example.com | 域名不同 | 不允許訪問 |
http://www.baidu.com | ||
http://www.example.com/a.js | 相同域下同一文件夾 | 允許訪問 |
http://www.example.com/b.js | ||
http://www.example.com/a.js | 相同域下不同文件夾 | 允許訪問 |
http://www.example.com/js/a.js |
注意:
1、ip相同,域名不同,也是跨域。
2、如果是協議和端口造成的跨域問題“前臺”是無能爲力的。
3、爲什麼要限制跨域訪問:安全問題。
如果一個網頁可以隨意地訪問另外一個網站的資源,那麼就有可能在客戶完全不知情的情況下出現安全問題。比如下面的操作就有安全問題:
1.用戶訪問www.mybank.com,登陸並進行網銀操作,這時cookie啥的都生成並存放在瀏覽器;
2.用戶突然想起件事,並迷迷糊糊的訪問了一個邪惡的網站www.xiee.com;
3.這時該網站就可以在它的頁面中,拿到銀行的cookie,比如用戶名,登陸token等,然後發起對www.mybank.com的操作;
4.如果這時瀏覽器不予限制,並且銀行也沒有做響應的安全處理的話,那麼用戶的信息有可能就這麼泄露了。
4、爲什麼要跨域
既然有安全問題,那爲什麼又要跨域呢? 有時公司內部有多個不同的子域,比如一個是cart.jd.com ,而應用是放在app.jd.com , 這時想從 app.jd.com去訪問 cart.jd.com 的資源就屬於跨域。
二、解決方案
使用跨域資源共享(CORS)來跨域
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。CORS需要瀏覽器和服務器同時支持。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低於IE10。
它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對於開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。因此,實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨源通信。
只需要在後臺中加上響應頭來允許域請求!在被請求的Response header中加入以下設置,就可以實現跨域訪問了!
//指定允許其他域名訪問
'Access-Control-Allow-Origin:*'//或指定域
//響應類型
'Access-Control-Allow-Methods:GET,POST'
//響應頭設置
'Access-Control-Allow-Headers:x-requested-with,content-type'
舉例:
@RequestMapping("/add")
public Result add(Long id, Integer num) {
/*CORS*/
response.setHeader("Access-Control-Allow-Origin", "http://localhost:9105");
response.setHeader("Access-Control-Allow-Credentials", "true");
/* 你的邏輯代碼*/
}
Spring Framework 4.2 GA爲CORS提供了第一類支持,使您比通常的基於過濾器的解決方案更容易和更強大地配置它。所以springMVC的版本要在4.2或以上版本才支持@CrossOrigin。
@CrossOrigin()註解來替代上面的兩行話 參考@CrossOrigin()詳解
@RequestMapping("/addGoodsToCartList")
@CrossOrigin(origins = "http://localhost:9105", allowCredentials = "true")//默認是ture
public Result addGoodsToCartList(Long itemId, Integer num) {
/*CORS*/
/* response.setHeader("Access-Control-Allow-Origin", "http://localhost:9105");
response.setHeader("Access-Control-Allow-Credentials", "true");*/
/*邏輯代碼*/
}
Access-Control-Allow-Origin
Access-Control-Allow-Origin是HTML5中定義的一種解決資源跨域的策略。
他是通過服務器端返回帶有Access-Control-Allow-Origin標識的Response header,用來解決資源的跨域權限問題。
使用方法:在response添加 Access-Control-Allow-Origin,例如
Access-Control-Allow-Origin:www.google.com |
也可以設置爲 * 表示該資源誰都可以用
前端JS代碼
//添加商品到購物車 $scope.addToCart=function(){ $http.get('http://localhost:9107/cart/addGoodsToCartList.do?itemId=' + $scope.sku.id +'&num='+$scope.num,{'withCredentials':true}).success( function(response){ ....... } ); } |
調用測試,可以實現跨域了。
CORS請求默認不發送Cookie和HTTP認證信息。如果要把Cookie發到服務器,一方面要服務器同意,指定Access-Control-Allow-Credentials字段。另一方面,開發者必須在AJAX請求中打開withCredentials屬性。否則,即使服務器同意發送Cookie,瀏覽器也不會發送。或者,服務器要求設置Cookie,瀏覽器也不會處理。
文主要介紹CORS解決方案
其他解決方案請參考 js處理的8種跨域方法