springboot CORS 跨域請求解決三大方案,springboot CorsFilter解決跨域問題


springboot CORS 跨域請求解決三大方案,springboot CorsFilter解決跨域問題

springboot CORS解決 No 'Access-Control-Allow-Origin' header is present on the requested resource

 

================================

©Copyright 蕃薯耀 2020-11-24

https://www.cnblogs.com/fanshuyao/

 

跨域請求,一般是在頁面調用ajax請求向別的應用服務發送請求,因域名不相同,導致跨域

解決跨域請求的方式有:

一、遠程服務器支持跨域請求(CORS 跨域)

二、使用nginx反向代理

三、服務器端使用Http請求

四、使用jsonp(需要應用服務器支持)

 

下面以遠程服務器支持跨域請求(CORS 跨域)為例:

其中有三種方式讓遠程服務器支持跨域請求

方式一、使用注解:@CrossOrigin

1、在類上加注解,表示類下所有方法都支持跨域請求

@CrossOrigin
@RestController
@RequestMapping("cross")
public class AaaController {

}

 

2、在方法加注解,表示該方法運動跨域請求

@RestController
@RequestMapping("cross")
public class AaaController {

    @CrossOrigin
    @RequestMapping("/bbb")
    public Result bbb(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ……
    }
}

 

方式二、實現WebMvcConfigurer接口,重寫addCorsMappings方法(官方文檔全局配置跨域請求使用的是此方式)

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.test.util.JsonUtil;


@Configuration
public class MvcConfig implements WebMvcConfigurer {

    /**
     * 解決跨域請求
     * @return
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowCredentials(true)
        .allowedOrigins("*")
        .allowedHeaders("*")
        .allowedMethods("*")
        .maxAge(3600);

        WebMvcConfigurer.super.addCorsMappings(registry);
    }



    /**
     * 解決@RestController返回json結果時,IE瀏覽器出現下載json文件的現象。
     * @return
     */
    @Bean
    public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        
        List<MediaType> supportedMediaTypes  = new ArrayList<MediaType>();
        supportedMediaTypes.add(new MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8")));
        supportedMediaTypes.add(new MediaType(MediaType.TEXT_HTML, Charset.forName("UTF-8")));
        jsonConverter.setSupportedMediaTypes(supportedMediaTypes);
        
        jsonConverter.setObjectMapper(JsonUtil.getMapper());//設置使用jackson轉換器
        
        return jsonConverter;
    }
    

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(jackson2HttpMessageConverter());
    }

    
}

 

方式三、使用CorsFilter過濾器

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class HttpFilterConfig {

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.setAllowCredentials(true);
        corsConfig.addAllowedOrigin(CorsConfiguration.ALL);
        corsConfig.addAllowedMethod(CorsConfiguration.ALL);
        corsConfig.addAllowedHeader(CorsConfiguration.ALL);
        //默認可不設置這個暴露的頭。這個為了安全問題,不能使用*。設置成*,后面會報錯:throw new IllegalArgumentException("'*' is not a valid exposed header value");
        //corsConfig.addExposedHeader("");
        corsConfig.setMaxAge(3600L);
        
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", corsConfig);
        
        FilterRegistrationBean<CorsFilter> corsBean = new FilterRegistrationBean<CorsFilter>(new CorsFilter(configSource));
        corsBean.setName("crossOriginFilter");
        corsBean.setOrder(0);//這個順序也有可能會有影響,盡量設置在攔截器前面
        return corsBean;
    }
    
    
}

 

前端頁面調用示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>跨域請求</title>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
</head>
<body>

    <div>跨域請求</div>
    
<script type="text/javascript">
function ajax(){
    console.log("ajax()");
    $.ajax({  
        //async: false,//設置為同步,默認為異步(一般不需要)  
        url : "http://aaa.com:7010/gtkjCghj/workflow/processes",  //aaa.com域名修改host文件
        type : "post",  
        dataType : "json",
        //contentType: "application/json;charset=UTF-8",//contentType如果設置成application/json;charset=UTF-8,就會會變成復雜請求,導致發送2次請求,第一次是options請求,第二次才是真正的請求。
        data : {
            "processName" : "報批",
            "gxDocNo": "f2-202000234",
            "ssotoken":"eyJpc3N1Y2Nlc3MiOiJ0cnVlIiwiZmFpbHJlc29uIjoiIiwiYWNjb3VudCI6Inplbmd6aW0iLCJ0b2tlbiI6ImE5YzA5YTdjYWRlOTQwNjFiNzdmYzMxNjhkZDI2Mzc3In0=.Eg4DFhERDQ=="
        },
        complete : function(XMLHttpRequest, textStatus){  
            //alert("textStatus="+textStatus);  
        },  
        error : function(XMLHttpRequest, textStatus, errorThrown){  
            if("error" == textStatus){  
                alert("服務器未響應,請稍候再試");  
            }else{  
                alert("請求失敗,textStatus="+textStatus);  
            }  
         },  
         success : function(data){  
             if(data != null){  
                 console.log("data===" + JSON.stringify(data));
             }else{  
                 alert("返回結果為空!");  
             }  
         }  
    }); 
};


ajax();
</script>

</body>
</html>

 

注意事項: 

需要注意的是ajax請求中的contentType

contentType默認的值是:application/x-www-form-urlencoded,當不設置或者為默認值時,這個是簡單請求,只發送1次真正的請求。
如果contentType設置成"application/json;charset=UTF-8"會變成復雜請求,導致發送2次請求,第一次是options請求,第二次才是真正的請求。

部分服務器,是禁止發送OPTIONS請求的,這樣會導致跨域問題:

jquery-3.4.1.min.js:2 OPTIONS http://test.com/gtkjCghj/workflow/processes 401 (Unauthorized)
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

 

簡單請求
只要同時滿足以下條件就屬於簡單請求
1、請求方法是以下三種方法之一:GET、POST、HEAD
2、Http的頭信息不超出以下幾種字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type。

Content-Type只限於三個值:application/x-www-form-urlencoded、multipart/form-data、text/plain

 

簡單請求的請求頭示例:
其中:Content-Type: application/x-www-form-urlencoded; charset=UTF-8

POST /gtkjCghj/workflow/processes HTTP/1.1
Host: aaa.com:7010
Connection: keep-alive
Content-Length: 212
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://127.0.0.1:7010
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://127.0.0.1:7010/gtkjCghj/static/cross.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

 

非簡單請求,發送OPTIONS的請求頭:

OPTIONS /gtkjCghj/workflow/processes HTTP/1.1
Host: aaa.com
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://aaa.com:7010
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: http://127.0.0.1:7010/gtkjCghj/static/cross.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

 

 

總結:cors跨域請求解決方案(建議采用方案1)

1、springboot CORS 跨域請求解決三大方案,springboot CorsFilter解決跨域問題

https://www.cnblogs.com/fanshuyao/p/14030944.html

 

2、cors-filter使用,cors-filter解決跨域訪問,cors-filter跨域請求

https://www.cnblogs.com/fanshuyao/p/14036848.html

 

3、org.ebaysf.web的cors-filter使用,cors-filter跨域請求

https://www.cnblogs.com/fanshuyao/p/14042293.html

 

4、java tomcat-catalina CorsFilter使用,apache tomcat-catalina CorsFilter使用

https://www.cnblogs.com/fanshuyao/p/14042420.html

 

5、springboot jsonp 跨域請求,springboot使用jsonp跨域

https://www.cnblogs.com/fanshuyao/p/14034014.html

 

 

(如果文章對您有幫助,歡迎捐贈,^_^)

================================

©Copyright 蕃薯耀 2020-11-24

https://www.cnblogs.com/fanshuyao/


免責聲明!

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



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