spring cloud gateway跨域全局CORS配置方式
在Spring 5 Webflux中,配置CORS,可以通過自定義WebFilter實(shí)現(xiàn):
注:此種寫法需真實(shí)跨域訪問,監(jiān)控header中才會(huì)帶相應(yīng)屬性。
代碼實(shí)現(xiàn)方式
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.http.HttpMethod;
import reactor.core.publisher.Mono;
import static org.springframework.web.cors.CorsConfiguration.ALL;
public class XXXApplication{
public static void main(String[] args) {
SpringApplication.run(XXXApplication.class, args);
}
private static final String MAX_AGE = "18000L";
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (!CorsUtils.isCorsRequest(request)) {
return chain.filter(ctx);
}
HttpHeaders requestHeaders = request.getHeaders();
ServerHttpResponse response = ctx.getResponse();
HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
if (requestMethod != null) {
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
}
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
return chain.filter(ctx);
};
}
}
配置實(shí)現(xiàn)方式
網(wǎng)上還提到一種配置寫法,實(shí)測(cè)好用:
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*"
springcloud gateway 跨域的解決
springcloud gateway提供的自帶的跨域過濾器有問題,前端還是會(huì)報(bào)跨域。zuul不會(huì)有這個(gè)問題。調(diào)試發(fā)現(xiàn)主要是游覽器發(fā)送嗅探請(qǐng)求(OPTIONS)時(shí),沒有返回跨域的響應(yīng)頭,從而游覽器報(bào)跨域問題。
驗(yàn)證
由于springcloud gateway為webflux與zuul不一樣,同一個(gè)服務(wù),采用spring內(nèi)置的跨域過濾器,zuul可以通過而gateway報(bào)錯(cuò)。具體配置如下:
1、gateway跨域配置
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
# 允許攜帶認(rèn)證信息
# 允許跨域的源(網(wǎng)站域名/ip),設(shè)置*為全部
# 允許跨域請(qǐng)求里的head字段,設(shè)置*為全部
# 允許跨域的method, 默認(rèn)為GET和OPTIONS,設(shè)置*為全部
# 跨域允許的有效期
allow-credentials: true
allowed-origins: '*'
allowed-headers: Content-Type,Content-Length, Authorization, Accept,X-Requested-With
allowed-methods: '*'
exposed-headers: Content-Type,Content-Length, Authorization, Accept,X-Requested-With
max-age: 3600
此配置無效,前端還是會(huì)報(bào)跨域問題,主要是前端發(fā)送OPTIONS請(qǐng)求時(shí)沒有返回跨域信息
2、zuul網(wǎng)關(guān)或者其它微服務(wù)servlet
向容器中注入跨域過濾器
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* @author ZhouChuGang
* @version 1.0
* @project langangkj-commonm
* @date 2020/5/4 12:24
* @Description 跨域過濾器配置
*/
@Slf4j
@configuration
@ConditionalOnMissingBean(CorsFilter.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class CorsFilterConfiguration {
public CorsFilterConfiguration() {
log.info("==========注入跨域過濾器=============");
}
@Bean("corsFilter")
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
// #允許向該服務(wù)器提交請(qǐng)求的URI,*表示全部允許
config.addAllowedOrigin(CorsConfiguration.ALL);
// 允許cookies跨域
config.setAllowCredentials(true);
// #允許訪問的頭信息,*表示全部
config.addAllowedHeader(CorsConfiguration.ALL);
// 允許提交請(qǐng)求的方法,*表示全部允許
config.addAllowedMethod(CorsConfiguration.ALL);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
@Autowired
@Qualifier("corsFilter")
private CorsFilter corsFilter;
/**
* 配置跨域過濾器
*/
@Bean
public FilterRegistrationBean<CorsFilter> corsFilterRegistration() {
FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(corsFilter);
registration.addUrlPatterns("/*");
registration.setName("corsFilter");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
}
此方案可以完美解決跨域問題。但是springcloud gateway 不是servlet 規(guī)范。
解決方案
1、gateway后面的微服務(wù)實(shí)現(xiàn)跨域
跨域由網(wǎng)關(guān)后面的服務(wù)實(shí)現(xiàn)。
2、實(shí)現(xiàn)一個(gè)過濾器,來做跨域允許
需要在響應(yīng)頭中加入以下信息
# 這個(gè)為請(qǐng)求頭中的 origin add_header 'Access-Control-Allow-Origin' '$http_origin' ; add_header 'Access-Control-Allow-Credentials' 'true' ; add_header 'Access-Control-Allow-Methods' 'PUT,POST,GET,DELETE,OPTIONS' ; add_header 'Access-Control-Allow-Headers' 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With' ;
3、采用nginx做代理,配置跨域響應(yīng)頭。(強(qiáng)烈推薦)
請(qǐng)求先到nginx,nginx再去請(qǐng)求gateway, 由nginx添加跨域響應(yīng)頭
add_header 'Access-Control-Allow-Origin' '$http_origin' ; add_header 'Access-Control-Allow-Credentials' 'true' ; add_header 'Access-Control-Allow-Methods' 'PUT,POST,GET,DELETE,OPTIONS' ; add_header 'Access-Control-Allow-Headers' 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With' ;
這里本人為了方便,采用第3中方案,測(cè)試完美解決!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring Retryable注解實(shí)現(xiàn)重試詳解
這篇文章主要介紹了spring Retryable注解實(shí)現(xiàn)重試詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Java中的SynchronousQueue阻塞隊(duì)列使用代碼實(shí)例
這篇文章主要介紹了Java中的SynchronousQueue阻塞隊(duì)列使用代碼實(shí)例,SynchronousQueue是無緩沖區(qū)的阻塞隊(duì)列,即不能直接向隊(duì)列中添加數(shù)據(jù),會(huì)報(bào)隊(duì)列滿異常,需要的朋友可以參考下2023-12-12
使用httpclient無需證書調(diào)用https的示例(java調(diào)用https)
JVM解密之解構(gòu)類加載與GC垃圾回收機(jī)制詳解
java正則表達(dá)式之Pattern與Matcher類詳解
Java實(shí)現(xiàn)調(diào)用第三方相關(guān)接口

