Tomcat默認不支持restful風格的put與delete請求、預檢請求相關的問題

Access to XMLHttpRequest at 'http://localhost:8080/employee/updateEmployee/' from origin 'http://localhost:63343' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

 

  一般我們會自定義一個攔截器實現登錄攔截,使用spring mvc的CorsFilter過濾器解決跨域的問題,然而當你的請求滿足了攔截器時,請求繼續向下執行,沒有問題,但是當你的請求不滿足攔截器時,將會出現跨域問題,哪怕你解決了跨域問題都未必有效。

因為自定義的攔截器會在CorsFilter過濾器之前執行,因此會產生跨域問題

  這時就可以使用自定義的Filter來解決跨域問題,因為過濾的是servlet的請求,我們的攔截器是spring mvc的攔截器,想要進入spring mvc的攔截器,前提是要進入spring mvc,進入springmvc 是通過dispatcherServler,滿足dispatcherServler中設置的請求才能進入,恰巧Filter可以對servlet進行攔截

  然而在使用自定義Filter時,要注意兩點

1、Tomcat默認不支持restful風格的put與delete請求

  這種情況下,我們可以選擇使用RequestMapping來接收請求,不使用put、delete;

  或者用其他的方式解決(這裏我沒有仔細去看)


//TODO 標個todo回頭在寫


2、預檢請求的問題

概念

  規範要求,對那些可能對服務器數據產生副作用的 HTTP 請求方法(特別是 GET 以外的 HTTP 請求,或者搭配某些 MIME 類型的 POST 請求),瀏覽器必須首先使用 OPTIONS 方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求。服務器確認允許之後,才發起實際的 HTTP 請求。簡單請求不會觸發CORS預檢請求,而非簡單請求則會觸發。

若請求滿足所有下述條件,則該請求可視為“簡單請求”,否則為非簡單請求:

  • 使用下列方法之一:GET POST HEAD
  • Fetch 規範定義了對 CORS 安全的首部字段集合,不得人為設置該集合之外的其他首部字段。該集合為:
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type ()
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width
  • Content-Type 的值僅限於下列三者之一:
  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded
  • 請求中的任意XMLHttpRequestUpload 對象均沒有註冊任何事件監聽器;XMLHttpRequestUpload 對象可以使用 XMLHttpRequest.upload 屬性訪問。
  • 請求中沒有使用 ReadableStream 對象。
  • 滿足上面所有的條件才不會發送預檢請求,在實際項目中我們的請求格式可能是application/json格式編碼,或者使用自定義請求頭都會觸發CORS的預檢請求。

  也就是説瀏覽器會判斷是否是複雜請求,若是複雜請求,這時瀏覽器會先發送一個域請求向後台確認,若能請求成功,在發送真正的請求到後台,這裏需要注意的是,預檢請求是不攜帶session的,不僅是session還有很多信息都是不攜帶的,所以使用session存儲登錄信息做登錄攔截的,會遇到跨域問題。

解決方案:

  一、幹掉預檢請求(不推薦)

  在攔截器中放過預檢請求,這種方式是很不推薦的,就像我看的一篇博客説的,前輩們怕房子不安全,造了個門,而你沒有鑰匙,於是你便拆了門。

  二、把請求轉換為簡單請求