跨域問題剖析 && SpringMVC跨域解決方案

Part1:跨域問題剖析

1.跨域問題出現的原因

跨域問題:一般是A瀏覽器請求了非同源,例如B服務器的URI時,所導致的問題。

2.瀏覽器為什么要限制同源?

同源目的:是為了保證用戶信息的安全,防止惡意的網站竊取數據。eg:比如銀行用戶的cookie信息。

3.同源的3個指標

所謂"同源"指的是"三個相同"。
1>協議相同
2>域名相同
3>端口相同

4.非同源受限制的3個行為

1>Cookie、LocalStorage 和 IndexDB 無法讀取。

2>DOM 無法獲得。

3>AJAX 請求不能發送。

其中第3條開發時碰到的最多。

5.解決非同源AJAX請求報錯

同源政策規定,AJAX請求只能發給同源的網址,否則就報錯。

除了架設服務器代理(瀏覽器請求同源服務器,再由后者請求外部服務),有三種方法規避這個限制。

1>JSONP
2>WebSocket
3>CORS

Part2:SpringMVC通過CORS協議解決跨域問題

1.CORS介紹

CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。

它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。

CORS需要瀏覽器和服務器同時支持。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。

整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對于開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。

因此,實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨源通信。

2.方法1:Spring-自定義Fliter:在response中添加CORS響應頭(Access-Control-Allow*)

3.方法2:SpringMVC4提供了非常方便的實現跨域的方法。在requestMapping中使用注解。

@CrossOrigin(origins = “http://kbiao.me”)

Part3:自己實際測試

1.跨域情境模擬:

前端index.html在電腦A上,頁面中有個submit按鈕來發送ajax請求。且請求url定位到后臺對應Handler:http://192.168.0.218:8080/InsureService/crossOrigin/detail

后臺服務器在電腦B上,Spring項目中書寫一個測試controller接收HTTP請求。代碼如下:

@Controller
@RequestMapping("/crossOrigin")
public class CrossOriginController {


    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    @ResponseBody
    public String savePayAndTrip(HttpServletRequest request){

        String reqStr = HttpUtils.getReqeustData(request);

        System.out.println("請求報文:" + reqStr);

        return reqStr;
    }//end method

}

2.跨域問題重現:

在上述情境準備下,前端請求的Origin為null,后端Origin為http://192.168.0.218:8080。兩者不同源,所以前端的ajax請求,無法到達后臺的Handler,也就不能被處理。(前端源為null,因為在本地電腦A直接在瀏覽器加載html文件發起請求導致。)

谷歌瀏覽器測試,截圖:
1.跨域錯誤前端信息

2.跨域問題錯誤細節

3.跨域問題解決:使用Spring的@CrossOrigin注解

@CrossOrigin注解,可以放在Controller類上,允許Controller中所有方法可被某個跨域請求;也可以放在Controller類中某一個方法上,指明當前方法可以被哪些跨域請求

示例代碼中:將@CrossOrigin加在Controller類上:

@Controller
@RequestMapping("/crossOrigin")
@CrossOrigin(origins = "*")   //跨域核心配置
public class CrossOriginController {


    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    @ResponseBody
    public String savePayAndTrip(HttpServletRequest request){

        String reqStr = HttpUtils.getReqeustData(request);

        System.out.println("請求報文:" + reqStr);

        return reqStr;
    }//end method

}
分析:

瀏覽器針對'非簡單請求'的跨域,會根據CORS協議在底層會發起兩次request:
(1)使用HTTP協議OPTIONS方法,發起的預檢請求(preflight request);
(2)發起正常請求

谷歌瀏覽器測試結果:
1.OPTIONS預檢請求
2.正常請求

參考文章(干貨滿滿)

1.阮一峰---瀏覽器同源政策及其規避方法
2.阮一峰---跨域資源共享 CORS 詳解
3.Spring MVC通過CROS協議解決跨域問題

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容