Springboot如何優雅的解決ajax+自定義headers的跨域請求


1、什么是跨域

由於瀏覽器同源策略(同源策略,它是由Netscape提出的一個著名的安全策略。現在所有支持JavaScript 的瀏覽器都會使用這個策略。所謂同源是指,域名,協議,端口相同。),凡是發送請求url的協議、域名、端口三者之間任意一與當前頁面地址不同即為跨域。

具體可以查看下表:

Springboot如何優雅的解決ajax+自定義headers的跨域請求

2、springboot如何解決跨域問題

1.普通跨域請求解決方案:

①請求接口添加注解@CrossOrigin(origins = "http://127.0.0.1:8020", maxAge = 3600)

說明:origins = "http://127.0.0.1:8020" origins值為當前請求該接口的域

②通用配置(所有接口都允許跨域請求)

新增一個configration類 或 在Application中加入CorsFilter和CorsConfiguration方法

@Configuration  
public class CorsConfig {  
    private CorsConfiguration buildConfig() {  
        CorsConfiguration corsConfiguration = new CorsConfiguration();  
        corsConfiguration.addAllowedOrigin("*"); // 1允許任何域名使用
        corsConfiguration.addAllowedHeader("*"); // 2允許任何頭
        corsConfiguration.addAllowedMethod("*"); // 3允許任何方法(post、get等) 
        return corsConfiguration;  
    }  

    @Bean  
    public CorsFilter corsFilter() {  
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();  
        source.registerCorsConfiguration("/**", buildConfig()); // 4  
        return new CorsFilter(source);  
    }  
}  

 

2.ajax自定義headers的跨域請求

$.ajax({
        type:"GET",
        url:"http://localhost:8766/main/currency/sginInState",
        dataType:"JSON",
        data:{
            uid:userId
        },
        beforeSend: function (XMLHttpRequest) {
            XMLHttpRequest.setRequestHeader("Authorization", access_token);
        },
        success:function(res){
            console.log(res.code)
        }
    })

 

此時請求http://localhost:8766/main/currency/sginInState接口發現OPTIONS http://localhost:8766/main/currency/sginInState 500錯誤,普通跨域的解決方案已經無法解決這種問題,為什么會出現OPTIONS請求呢?

Springboot如何優雅的解決ajax+自定義headers的跨域請求

原因

瀏覽器會在發送真正請求之前,先發送一個方法為OPTIONS的預檢請求 Preflighted requests 這個請求是用來驗證本次請求是否安全的,但是並不是所有請求都會發送,需要符合以下條件:

  • 請求方法不是GET/HEAD/POST

  • POST請求的Content-Type並非application/x-www-form-urlencoded, multipart/form-data, 或text/plain

  • 請求設置了自定義的header字段

對於管理端的接口,我有對接口進行權限校驗,每次請求需要在header中攜帶自定義的字段(token),所以瀏覽器會多發送一個OPTIONS請求去驗證此次請求的安全性。

為何OPTIONS請求是500呢?

OPTIONS請求只會攜帶自定義的字段,並不會將相應的值帶入進去,而后台校驗token字段時 token為NULL,所以驗證不通過,拋出了一個異常。

那么我們現在來解決這種問題:

① spring boot項目application.yml中添加

spring:
mvc:
dispatch-options-request: true 

 

注意:這種解決方案可能在某些情況下並不能解決OPTIONS問題,原因可能是環境問題,也可能是復雜的自定義filter過濾器配置問題等。

②添加過濾器配置

第一步:手寫RequestFilter請求過濾器配置類此類需要實現HandlerInterceptor類,HandlerInterceptor類是org.springframework.web.servlet.HandlerInterceptor下的。

具體代碼實現:

@Component
public class RequestFilter implements HandlerInterceptor {
   public boolean preHandler(HttpServletRequest request,HttpServletResponse response,Object handler){
       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");
       // 如果是OPTIONS請求則結束
       if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
           response.setStatus(HttpStatus.NO_CONTENT.value());
           return false;
       }
       return true;
   }
}

 

第二步:手寫MyWebConfiguration此類需要繼承WebMvcConfigurationSupport。

注意:WebMvcConfigurationSupport是2.x版本以上的,1.x版本為WebMvcConfigurerAdapter 。

具體代碼實現:

@Component
public class MyWebConfiguration extends WebMvcConfigurationSupport{
    @Resource
    private RequestFilter requestFilter;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 跨域攔截器
        registry.addInterceptor(requestFilter).addPathPatterns("/**");
    }
}

 

Springboot如何優雅的解決ajax+自定義headers的跨域請求

此時我們就完美解決了ajax+自定義headers的跨域請求了,歡迎隨時交流學習。

(點擊文字可跳轉)

1. 深究Spring中Bean的生命周期

2. 深入SpringBoot核心注解原理

3.線上環境部署概覽

4.Springboot Vue shiro 實現前后端分離、權限控制


免責聲明!

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



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