淺析SpringSecurity對跨域非簡單請求的Prefight預檢請求的處理:requestMatchers(CorsUtils::isPreFlightRequest).permitAll()、及簡單請求與非簡單請求的理解


  先說解決方案吧,我們代碼里的解決方案:

.antMatchers("/examRoom/find").permitAll() .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() // 關鍵這行,就是允許Prefight預檢請求
.antMatchers(HttpMethod.POST, "/login").permitAll()

  Prefight預檢請求就是一個 options 請求,我們可以點進去看源碼:

public static boolean isPreFlightRequest(HttpServletRequest request) { return HttpMethod.OPTIONS.matches(request.getMethod()) && request.getHeader("Access-Control-Request-Method") != null; }

  requestMatchers(CorsUtils::isPreFlightRequest).permitAll()的作用是將PreflightRequest不做攔截。

一、為什么需要preflight request

  我們都知道瀏覽器的同源策略,就是出於安全考慮,瀏覽器會限制從腳本發起的跨域HTTP請求,像XMLHttpRequest和Fetch都遵循同源策略。

  瀏覽器限制跨域請求一般有兩種方式:(1)瀏覽器限制發起跨域請求;(2)跨域請求可以正常發起,但是返回的結果被瀏覽器攔截了。

  一般瀏覽器都是第二種方式限制跨域請求,那就是說請求已到達服務器,並有可能對數據庫里的數據進行了操作,但是返回的結果被瀏覽器攔截了,那么我們就獲取不到返回結果,這是一次失敗的請求,但是可能對數據庫里的數據產生了影響。

  為了防止這種情況的發生,規范要求,對這種可能對服務器數據產生副作用的HTTP請求方法,瀏覽器必須先使用OPTIONS方法發起一個預檢請求,從而獲知服務器是否允許該跨域請求:如果允許,就發送帶數據的真實請求;如果不允許,則阻止發送帶數據的真實請求

  瀏覽器將CORS請求分成兩類:簡單請求和非簡單請求。

  瀏覽器對這兩種請求的處理是不一樣的,非簡單請求的CORS請求,會在正式通信之前,增加一次HTTP查詢請求,稱為"預檢"請求(preflight)。

二、簡單請求與非簡單請求

  詳見之前總結的這篇博客:淺析http簡單請求與復雜請求

  CORS請求,瀏覽器與服務器交互的過程,這上面的坑主要就是Preflight。如果我們的后台用了安全管理框架(比如Spring Security),並且沒有對Preflight這個請求做出相應的處理,那么這個請求會導致權限管控失敗(比如無法登錄)。

  因為Preflight不攜帶Cookie,即不攜帶JSESSIONID,因此Spring Security攔截器會認為你沒有登錄。

  由於 Prefight 預檢請求,實際就是一個 options 請求,所以我們也可以允許所有 options 請求,這樣解決這個問題。

@Override protected void configure(HttpSecurity http) throws Exception { http.cors().and() //跨域請求會先進行一次options請求,允許 options 請求
 .antMatchers(HttpMethod.OPTIONS).permitAll() ... }

三、簡單請求與非簡單請求的請求流程

  詳細內容看這篇文檔,官方描述:Cross-Origin Resource Sharing (CORS):https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

1、簡單請求

  這在客戶端和服務器之間執行簡單的交換,使用 CORS 標頭來處理權限:

2、預檢請求

  與“簡單請求”(上面討論過)不同,對於“預檢”請求,瀏覽器首先使用該OPTIONS方法向另一個源上的資源發送 HTTP 請求,以確定實際請求是否可以安全發送。跨站點請求是這樣預檢的,因為它們可能會對用戶數據產生影響。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM