1. 程式人生 > >跨域請求詳解

跨域請求詳解

author localhost rdquo 階段 org web 復雜 跨域問題 表示

跨域請求總體分為兩種類型:簡單請求和復雜請求,即simple request和preflight request。

一、簡單請求

simple request的請求需要,滿足以下條件:

1.請求方法只能是GET,HEAD,POST

2.Accept、Accept-Language、Content-Language、Content-Type、DPR、Downlink、Save-Data、Viewport-Width、Width

3.第二個條件中的Content-Type只能是application/x-www-form-urlencoded、multipart/form-data、text/plain其中的一種

4.沒有特殊js代碼(參考https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests)

對於simple request請求,盡管這個請求是跨域的,它也會被瀏覽器直接放行。

但是瀏覽器拿到response後並不會把 response 直接暴露給用戶程序,而是去檢查這個 response 的 headers 中有沒有 Access-Control-Allow-Origin,以及這個 header 的 value 包含 request 發出的地址(也就是“域”)。

如果兩個條件都滿足, response 會被返回給發出請求的程序;如果沒有這個 header 或者 value 不對, response 就會被攔截下來,因為在瀏覽器看來,這個 response 不屬於你,因為服務器沒有明確允許你這個“域”來請求它。

二、復雜請求

對於復雜請求,瀏覽器先發送一個pre-flight請求,通常是一個OPTIONS方法的請求,根據服務器響應的response的headers進行校驗,若校驗通過,則表明服務器允許訪問,再發送真正的請求。

通常要校驗的數據項有:Access-Control-Allow-Origin, Access-Control-Allow-Methods、Access-Control-Allow-Headers以及其他的Access-Control-*數據項。

下面是我們的一個跨域請求示例。本機63342端口的網頁通過ajax訪問8080端口的接口,存在跨域問題。

第一個是pre-flight請求,服務器收到請求並響應,response header中返回了Access-Control-Allow-Origin、Access-Control-Allow-Methods以及Access-Control-Allow-Headers等,

表示當前服務器允許http://localhost:63342域的GET請求(並且該請求包含name為authorization的header數據)訪問。如果不符合該條件則真正的請求不會被發送。

技術分享圖片

因為我們的請求符合服務器所要求的的條件,所以真正的請求被發送,請求數據如下:

技術分享圖片

我麽可以看到請求成功,一個完整的跨域請求就完成了。

spring4.2之後提供了@CrossOrigin註解來表明接口的跨域特性。

springMVC的請求流程是Request->Dispatchservlet->HandlerMappin(uri和handler的映射關系)->HandlerAdapter(適配器用於執行handler)->ModerAndView->ViewResolver->Response

CrossOrigin註解在HandlerAdapter階段起作用,當檢測到請求是preflight請求(滿足三個條件,請求方法為OPTIONS、請求head包含Origin和Access-Control-Request-Method)時,

spring給本次請求適配的handler是PreFlightHandler實例,該handler專門處理preflight請求,判斷是否拒絕訪問或者允許訪問時允許訪問的域、請求方法、請求必須的header。

真正的請求發送之後就是則會經過CorsInterceptor攔截器,其前置方法preHandle也會對跨域請求進行校驗,校驗通過則設置一些響應數據頭,然後交給下一級攔截器或者controller處理,校驗不通過則響應瀏覽器禁止訪問。

跨域請求詳解