原鏈接地址: http://blog.csdn.net/badboyer/article/details/51261083
CORS 跨域 access-control-allow-headers 的問題
最近項目裏需要處理跨域請求,遇到了一些問題,中間走了很多坑,深挖了很多細節,受益良多。
cors在跨域解決方案中算是很好用的,網上資料一大堆,只需要在服務器端進行配置即可。
配置方法網上也很多,我簡單記錄下,
主要用到cors-filter-1.7.jar 和java-property-utils-1.9.jar 這兩個jar包,其實cors-filter jar包最新的已經出到2.5了
不過1.7的也能用。然後在web.xml裏面配置一個filter
- <span style="white-space:pre"> </span><filter>
- <filter-name>CORS</filter-name>
- <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
- <init-param>
- <param-name>cors.allowOrigin</param-name>
- <param-value>*</param-value>
- </init-param>
- <init-param>
- <param-name>cors.supportedMethods</param-name>
- <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
- </init-param>
- <init-param>
- <param-name>cors.supportedHeaders</param-name>
- <param-value>Accept, Origin, XRequestedWith, Content-Type, LastModified</param-value>
- </init-param>
- <init-param>
- <param-name>cors.exposedHeaders</param-name>
- <param-value>SetCookie</param-value>
- </init-param>
- <init-param>
- <param-name>cors.supportsCredentials</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>CORS</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
普通的ajax請求測試時沒有問題的,但是 我在上傳文件跨域的時候遇到個莫名其妙的問題,用chrome上傳不好使,用firefox好使。 我
配置的沒有問題,代碼也沒什麼問題,那麼我猜測問題可能是瀏覽器的。 通過開發工具抓包,我發現chrome的請求內容是這樣的
下面的是firefox的
可以看到chrome瀏覽器多了個access-control-allow-headers 頭,而firefox則沒有。通過Fiddler模擬請求,發現就是這個
屬性的問題,去掉的話,就能發送成功。 我又上cors的官網,找到了這麼個圖片
cors過濾器的過濾流程清晰易懂,看起來還是挺好理解的,後來我又查看了源碼,發現在判斷access-control-allow-headers頭的時候會根據xml裏面cors.supportedHeaders配置的進行比對,如果這個頭沒有配置就返回403,我配置了,但是和瀏覽器配置的不一樣我配置的是ContentType,但瀏覽器發送的是Content-Type,多了個橫槓 快哭了,看起來一個小問題,水卻很深啊。 在上圖中可以看到,會先判斷是不是帶origin頭,如果帶的話,纔會判斷access-control-allow-headers頭,這是個自定義的頭信息。
在調試的過程中發現springmvc 默認是不支持options 請求, 要想支持這個請求,需要在web.xml的DispatcherServlet 增加
<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>
同時,在RequestMapping中需要知道method是options的,這樣springmvc就可以接收到options請求。
options請求比較特殊,是個透明請求,一般在跨域的時候瀏覽器會先發個options請求,詢問服務器是否支持跨域, access-control-allow-method表示後面實際發送數據的請求方法, 這個方法名需要包含在cors.supportedMethods 的配置。
CORS可以分成兩種:
- 簡單請求
- 複雜請求
一個簡單的請求大致如下:
-
HTTP方法是下列之一
-
HEAD
-
GET
-
POST
-
-
HTTP頭包含
-
Accept
-
Accept-Language
-
Content-Language
-
Last-Event-ID
-
Content-Type
,但僅能是下列之一-
application/x-www-form-urlencoded
-
multipart/form-data
-
text/plain
-
-
任何一個不滿足上述要求的請求,即被認爲是複雜請求。一個複雜請求不僅有包含通信內容的請求,同時也包含預請求(preflight request)。