前后端分離java、jwt項目進行CORS跨域、解決非簡單請求跨域問題、兼容性問題


情況描述:

最近在部署一個前后端分離的項目出現了跨域問題*,

項目使用jwt進行鑒權,需要前端請求發起攜帶TOKEN的請求*,請求所帶的token無法成功發送給后端,

使用跨域后出現了兼容性問題:Chrome、Firefox瀏覽器正常,而IE還是報跨域錯誤

一、跨域問題在項目中可以使用CORS解決

方式一

@CrossOrigin

在每個controller類加上

 

方式二 直接在spring-mvc中加入配置

    <!-- 接口跨域配置 -->

    <mvc:cors>

        <mvc:mapping path="/**"

                     allowed-origins="*"

                     allowed-methods="POST, GET, OPTIONS, DELETE, PUT"

                     allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"

                     allow-credentials="true" />

    </mvc:cors>

方式三 可以在interceptor中向response增加header

        response.setHeader("Access-Control-Allow-Origin", "*");

        response.setHeader("Access-Control-Allow-Credentials", "true");

        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");

        response.setHeader("Access-Control-Max-Age", "86400");

        response.setHeader("Access-Control-Allow-Headers", "Authorization,Overwrite, Destination, Content-Type, Depth, User-Agent, Translate, Range, Content-Range, Timeout, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Location, Lock-Token, If");

 

上面三種方式對一般的簡單跨域請求有效,可以滿足大部分需要。但遇到非簡單跨域請求的情況,就會出現問題,需要做一下調整。

 

二、復雜請求下需要對options預檢請求進行處理

 

前后端分離的項目中,瀏覽器請求中經常會出現非簡單跨域請求,這將會發送請求2次,第一條由瀏覽器發起請求為options的預檢請求,再根據服務器的返回內容由瀏覽器判斷服務器是否允許此次請求,第二條才是method中的get,post或者put等,並且第一條無任何數據返回,第二條才正常返回數據。

 

所以我們會遇到:我們處理token的攔截器(非簡單情況,header的authorization攜帶了token進行鑒權),在接收到option的時候將這個預檢請求當成正常的請求,而options請求時無法在header攜帶token的,因此后端將會把第一個請求打回,導致第二個請求無法正常發起。

 

非簡單情況(含以下之一):

  1. 請求方式:PUT、DELETE
  2. 自定義頭部字段
  3. 發送json格式數據
  4. 正式通信之前,瀏覽器會先發送OPTION請求,進行預檢,這一次的請求稱為“預檢請求”
  5. 服務器成功響應預檢請求后,才會發送真正的請求,並且攜帶真實數據

 

解決方式  在后端中對options請求進行直接給通過(只要返回200、204,瀏覽器即判斷服務器允許請求)

增加一個CorsInterceptor

public class CorsInterceptor implements HandlerInterceptor {

//使用了方式三、進行CORS配置

        response.setHeader("Access-Control-Allow-Origin", "*");

        response.setHeader("Access-Control-Allow-Credentials", "true");

        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");

        response.setHeader("Access-Control-Max-Age", "86400");

        response.setHeader("Access-Control-Allow-Headers", "Authorization,Overwrite, Destination, Content-Type, Depth, User-Agent, Translate, Range, Content-Range, Timeout, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Location, Lock-Token, If");

        if(HttpMethod.OPTIONS.toString().equals(httpServletRequest.getMethod())){

            response.setStatus(HttpStatus.NO_CONTENT.value());

            System.out.println("是options請求、跳過");

            return false;

        }

        return true;

    }

}

  

spring-mvc中加載這個CorsInterceptor,置於token處理之前

        <mvc:interceptor>

            <mvc:mapping path="/**" />

            <bean class="cn.gdyvc.interceptor.CorsInterceptor" />

        </mvc:interceptor>

三、CORS瀏覽器兼容問題

 

最后部署完成,但是Chrome、Firefox瀏覽器正常,而IE還是報跨域錯誤,遇到了Internet Explorer與Access-Control-Allow-Methods的CORS問題

剛開始跨域配置根據網上的的設置將Access-Control-Allow-Headers對應設置為“*”,而Ie的是不能夠響應*的,需要將header的各列單獨列出來

 

 

 

參考鏈接:

https://www.jianshu.com/p/5c637bfcc674

https://stackoverflow.com/questions/51857247/ie-cors-access-control-allow-headers-error-even-though-headers-are-specified

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers

 


免責聲明!

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



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