spring cloud gateway跨域全局CORS配置方式
在Spring 5 Webflux中,配置CORS,可以通過自定義WebFilter實現:
注:此種寫法需真實跨域訪問,監控header中才會帶相應屬性。
代碼實現方式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';@Beanpublic 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); };}}配置實現方式
網上還提到一種配置寫法,實測好用:
spring: cloud: gateway: globalcors:corsConfigurations: ’[/**]’: allowedOrigins: '*' allowedMethods: '*' allowedHeaders: '*'springcloud gateway 跨域的解決
springcloud gateway提供的自帶的跨域過濾器有問題,前端還是會報跨域。zuul不會有這個問題。調試發現主要是游覽器發送嗅探請求(OPTIONS)時,沒有返回跨域的響應頭,從而游覽器報跨域問題。
驗證由于springcloud gateway為webflux與zuul不一樣,同一個服務,采用spring內置的跨域過濾器,zuul可以通過而gateway報錯。具體配置如下:
1、gateway跨域配置spring: cloud: gateway: globalcors:cors-configurations: ’[/**]’: # 允許攜帶認證信息 # 允許跨域的源(網站域名/ip),設置*為全部 # 允許跨域請求里的head字段,設置*為全部 # 允許跨域的method, 默認為GET和OPTIONS,設置*為全部 # 跨域允許的有效期 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
此配置無效,前端還是會報跨域問題,主要是前端發送OPTIONS請求時沒有返回跨域信息
2、zuul網關或者其它微服務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();// #允許向該服務器提交請求的URI,*表示全部允許config.addAllowedOrigin(CorsConfiguration.ALL);// 允許cookies跨域config.setAllowCredentials(true);// #允許訪問的頭信息,*表示全部config.addAllowedHeader(CorsConfiguration.ALL);// 允許提交請求的方法,*表示全部允許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 規范。
解決方案1、gateway后面的微服務實現跨域跨域由網關后面的服務實現。
2、實現一個過濾器,來做跨域允許需要在響應頭中加入以下信息
# 這個為請求頭中的 originadd_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做代理,配置跨域響應頭。(強烈推薦)
請求先到nginx,nginx再去請求gateway, 由nginx添加跨域響應頭
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中方案,測試完美解決!
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。
相關文章:
1. React+umi+typeScript創建項目的過程2. ASP中常用的22個FSO文件操作函數整理3. 解決ASP中http狀態跳轉返回錯誤頁的問題4. ASP調用WebService轉化成JSON數據,附json.min.asp5. 三個不常見的 HTML5 實用新特性簡介6. ASP編碼必備的8條原則7. SharePoint Server 2019新特性介紹8. 無線標記語言(WML)基礎之WMLScript 基礎第1/2頁9. ASP.NET Core 5.0中的Host.CreateDefaultBuilder執行過程解析10. Warning: require(): open_basedir restriction in effect,目錄配置open_basedir報錯問題分析
