Spring Cloud Gateway网关之跨域支持
为什么要在网关支持跨域
互联网公司的系统基本上都是前后端分离的,如果不支持跨域,则当前端域名和后端暴露接口域名不完全一致时,前端就无法正常请求接口,这个时候,就需要后端支持跨域,而对跨域的支持,正常情况下都是在网关层面做支持,故在spring cloud gateway中支持跨域是很常见的场景。
方式一(推荐,尽可能把网关升级到2.2.x以上版本,低版本很多不完善到地方)
针对SpringCloudGateway2.2.x以上版本 可以直接使用自带的跨域配置即可如下(直接在application.yaml添加配置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| spring: cloud: gateway: filter: remove-hop-by-hop: headers: - trailer - te - keep-alive - transfer-encoding - upgrade - proxy-authenticate - connection - proxy-authorization - x-application-context - access-control-allow-credentials - access-control-allow-headers - access-control-allow-methods - access-control-allow-origin - access-control-max-age - vary globalcors: corsConfigurations: '[/**]': allowCredentials: true allowedOrigins: "*" allowedHeaders: "*" allowedMethods: "*" maxAge: 3628800
|
方式二(针对SpringCloudGateway2.1.x及以下版本)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Bean public WebFilter corsFilter() { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); if (!CorsUtils.isCorsRequest(request)) { return chain.filter(exchange); } ServerHttpResponse response = exchange.getResponse(); HttpHeaders headers = response.getHeaders(); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*"); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST,GET,OPTIONS,DELETE,PUT"); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "content-type"); headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3628800"); return chain.filter(exchange); }; }
|
方式三(针对SpringCloudGateway2.1.x及以下版本)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; import org.springframework.web.util.pattern.PathPatternParser;
@Configuration public class CorsConfig {
@Bean public CorsWebFilter corsFilter(){ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser()); source.registerCorsConfiguration("/**", buildConfig()); return new CorsWebFilter(source); }
private CorsConfiguration buildConfig(){ CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("content-type"); corsConfiguration.addAllowedMethod("POST,GET,OPTIONS,DELETE,PUT"); corsConfiguration.setMaxAge(3628800L);
return corsConfiguration; } }
|
通过以上方式配置之后可能还会存在某些浏览器跨域存在问题,比如搜狗浏览器可能就会报跨域问题,导致请求异常,这个时候需要增加多一个过滤器即可解决,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono;
import java.util.Arrays;
@Component public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {
@Override public int getOrder() { return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1; }
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange).then(Mono.defer(() -> { exchange.getResponse().getHeaders().entrySet().stream() .filter(kv -> kv.getValue() != null && kv.getValue().size() > 1) .filter(kv -> kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)) .forEach(kv -> kv.setValue(Arrays.asList(kv.getValue().get(0))));
return chain.filter(exchange); })); } }
|