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

狀況描述:前端

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

項目使用jwt進行鑑權,須要前端請求發起攜帶TOKEN的請求*,請求所帶的token沒法成功發送給後端,json

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

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

方式一跨域

@CrossOrigin瀏覽器

在每一個controller類加上spring-mvc

 

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

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

    <mvc:cors>app

        <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");

 

上面三種方式對通常的簡單跨域請求有效,能夠知足大部分須要。但遇到非簡單跨域請求的狀況,就會出現問題,須要作一下調整。

 

2、複雜請求下須要對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 {

//使用了方式3、進行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>

3、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

相關文章
相關標籤/搜索