spring cloud gateway跨域全局CORS配置方式
在Spring 5 Webflux中,配置CORS,可以通過(guò)自定義WebFilter實(shí)現(xiàn):
注:此種寫(xiě)法需真實(shí)跨域訪問(wèn),監(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)上還提到一種配置寫(xiě)法,實(shí)測(cè)好用:
spring: cloud: gateway: globalcors: corsConfigurations: '[/**]': allowedOrigins: "*" allowedMethods: "*" allowedHeaders: "*"
springcloud gateway 跨域的解決
springcloud gateway提供的自帶的跨域過(guò)濾器有問(wèn)題,前端還是會(huì)報(bào)跨域。zuul不會(huì)有這個(gè)問(wèn)題。調(diào)試發(fā)現(xiàn)主要是游覽器發(fā)送嗅探請(qǐng)求(OPTIONS)時(shí),沒(méi)有返回跨域的響應(yīng)頭,從而游覽器報(bào)跨域問(wèn)題。
驗(yàn)證
由于springcloud gateway為webflux與zuul不一樣,同一個(gè)服務(wù),采用spring內(nèi)置的跨域過(guò)濾器,zuul可以通過(guò)而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
此配置無(wú)效,前端還是會(huì)報(bào)跨域問(wèn)題,主要是前端發(fā)送OPTIONS請(qǐng)求時(shí)沒(méi)有返回跨域信息
2、zuul網(wǎng)關(guān)或者其它微服務(wù)servlet
向容器中注入跨域過(guò)濾器
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 跨域過(guò)濾器配置 */ @Slf4j @configuration @ConditionalOnMissingBean(CorsFilter.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public class CorsFilterConfiguration { public CorsFilterConfiguration() { log.info("==========注入跨域過(guò)濾器============="); } @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); // #允許訪問(wèn)的頭信息,*表示全部 config.addAllowedHeader(CorsConfiguration.ALL); // 允許提交請(qǐng)求的方法,*表示全部允許 config.addAllowedMethod(CorsConfiguration.ALL); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } @Autowired @Qualifier("corsFilter") private CorsFilter corsFilter; /** * 配置跨域過(guò)濾器 */ @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; } }
此方案可以完美解決跨域問(wèn)題。但是springcloud gateway 不是servlet 規(guī)范。
解決方案
1、gateway后面的微服務(wù)實(shí)現(xiàn)跨域
跨域由網(wǎng)關(guān)后面的服務(wù)實(shí)現(xiàn)。
2、實(shí)現(xiàn)一個(gè)過(guò)濾器,來(lái)做跨域允許
需要在響應(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)文章
基于Spark實(shí)現(xiàn)隨機(jī)森林代碼
這篇文章主要為大家詳細(xì)介紹了基于Spark實(shí)現(xiàn)隨機(jī)森林代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08Springboot中如何使用過(guò)濾器校驗(yàn)PSOT類型請(qǐng)求參數(shù)內(nèi)容
在Springboot中創(chuàng)建過(guò)濾器,用來(lái)過(guò)濾所有POST類型請(qǐng)求并獲取body中的參數(shù)進(jìn)行校驗(yàn)內(nèi)容是否合法,該方法僅適用于POST類型請(qǐng)求,本文給大家介紹Springboot中如何使用過(guò)濾器校驗(yàn)PSOT類型請(qǐng)求參數(shù)內(nèi)容,感興趣的朋友一起看看吧2023-08-08Java設(shè)計(jì)模式之責(zé)任鏈模式的概念、實(shí)現(xiàn)以及netty中的責(zé)任鏈模式
這篇文章主要給大家介紹了關(guān)于設(shè)計(jì)模式之責(zé)任鏈模式的概念、實(shí)現(xiàn)以及netty中的責(zé)任鏈模式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12java?中如何實(shí)現(xiàn)?List?集合去重
這篇文章主要介紹了java?中如何實(shí)現(xiàn)?List?集合去重,List?去重指的是將?List?中的重復(fù)元素刪除掉的過(guò)程,下文操作操作過(guò)程介紹需要的小伙伴可以參考一下2022-05-05SpringBoot框架aop切面的execution表達(dá)式解讀
這篇文章主要介紹了SpringBoot框架aop切面的execution表達(dá)式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05MyBatis使用注解開(kāi)發(fā)和無(wú)主配置文件開(kāi)發(fā)的情況
這篇文章主要介紹了MyBatis使用注解開(kāi)發(fā)和無(wú)主配置文件開(kāi)發(fā)的情況,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03