SpringCloud微服務(wù)中跨域配置的方法詳解
跨域,指的是瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì) javascript 施加的安全限制。
同源策略,指的是協(xié)議,域名,端口都要相同,其中有一個(gè)不同都會(huì)產(chǎn)生跨域。
跨域相關(guān)含義:
- Access-Control-Allow-Origin:服務(wù)器允許請(qǐng)求的源;
- Access-Control-Allow-Headers: 服務(wù)器允許使用的頭;
- Access-Control-Allow-Methods: 真實(shí)請(qǐng)求允許的方法;
- Access-Control-Allow-Credentials: 是否允許用戶發(fā)送、處理 cookie;
- Access-Control-Max-Age: 預(yù)檢請(qǐng)求的有效期,單位為秒。有效期內(nèi),不會(huì)重復(fù)發(fā)送預(yù)檢請(qǐng)求;
Java微服務(wù)中解決跨域問(wèn)題主要分為如下情況:
情況1:針對(duì)單個(gè)服務(wù)的跨域問(wèn)題,增加允許跨域配置類(lèi)即可。
如,前端vue+業(yè)務(wù)微服務(wù)
情況2:有網(wǎng)關(guān)時(shí),網(wǎng)關(guān)配置允許跨域,微服務(wù)不配置。微服務(wù)項(xiàng)目網(wǎng)關(guān)服務(wù)為Spring Cloud Gateway,則要求所有請(qǐng)求統(tǒng)一走網(wǎng)關(guān),無(wú)需給每個(gè)微服務(wù)都配置跨域,只需要給網(wǎng)關(guān)微服務(wù)gateway配置跨域即可。
如,前端vue+網(wǎng)關(guān)服務(wù)gateway+業(yè)務(wù)微服務(wù)
情況3:有網(wǎng)關(guān)時(shí),網(wǎng)關(guān)配置允許跨域,微服務(wù)配置允許跨域。需要在網(wǎng)關(guān)的配置里加上重復(fù)請(qǐng)求頭。配置DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_UNIQUE。此時(shí)走不走網(wǎng)關(guān),都沒(méi)有跨域問(wèn)題。
如,前端vue+網(wǎng)關(guān)服務(wù)gateway+業(yè)務(wù)微服務(wù)/認(rèn)證授權(quán)微服務(wù)
情況4:網(wǎng)關(guān)不配置,微服務(wù)配置允許跨域。請(qǐng)求如果走網(wǎng)關(guān),則會(huì)存在跨域問(wèn)題。不走網(wǎng)關(guān),直接訪問(wèn)微服務(wù),沒(méi)有跨域問(wèn)題。
情況5:網(wǎng)關(guān)不配置,微服務(wù)不配置。走不走網(wǎng)關(guān)都會(huì)存在跨域問(wèn)題。
情況1
單個(gè)springboot微服務(wù)的跨域配置如下
若springboot版本為2.4.0以前,則設(shè)置請(qǐng)求源為
corsConfiguration.addAllowedOrigin(“*”);
若springboot版本為2.4.0以后,則設(shè)置請(qǐng)求源為
corsConfiguration.setAllowedOriginPatterns(Collections.singletonList(“*”));
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
// 跨域配置源
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//設(shè)置跨域的配置信息
CorsConfiguration corsConfiguration = new CorsConfiguration();
//1,允許任何來(lái)源
corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
//2,允許任何請(qǐng)求頭
corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
//3,允許任何方法
corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
//4,允許憑證
corsConfiguration.setAllowCredentials(true);
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
}
其中,若在springboot2.3.10版本中使用corsConfiguration.addAllowedOrigin(“*”);是可以解決跨域問(wèn)題的,若在springboot2.7.0版本中使用,會(huì)發(fā)現(xiàn)報(bào)跨域問(wèn)題,查看后臺(tái)日志提示如下異常:
When allowCredentials is true, allowedOrigins cannot contain the special value "*"since that cannot be set on the “Access-Control-Allow-Origin” response header. To allow credentials to a set of origins, list them explicitly or consider using “allowedOriginPatterns” instead.
可見(jiàn),不能在 corsConfiguration.setAllowCredentials(true)的時(shí)候?qū)ddAllowedOrigin設(shè)置為"*",而要使用 allowedOriginPatterns這個(gè)字段來(lái)設(shè)置origin。
其實(shí),也可以采用重寫(xiě)WebMvcConfigurer的方式或使用注解@CrossOrigin的方式。
情況2
gateway網(wǎng)關(guān)服務(wù)中跨域配置類(lèi)如下
若springboot版本為2.4.0以前,則設(shè)置請(qǐng)求源為
corsConfiguration.addAllowedOrigin(“*”);
若springboot版本為2.4.0以后,則設(shè)置請(qǐng)求源為
corsConfiguration.setAllowedOriginPatterns(Collections.singletonList(“*”));
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
// 跨域配置源
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//設(shè)置跨域的配置信息
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 允許所有請(qǐng)求來(lái)源進(jìn)行跨域
//corsConfiguration.addAllowedOrigin("*");
// spring boot2.4以后的配置
corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
// 允許所有頭進(jìn)行跨域
corsConfiguration.addAllowedHeader("*");
// 允許所有請(qǐng)求方式進(jìn)行跨域
corsConfiguration.addAllowedMethod("*");
// 允許攜帶cookie進(jìn)行跨域
corsConfiguration.setAllowCredentials(true);
//任意路徑都需要跨域配置
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsWebFilter(source);
}
}
注:需要去掉業(yè)務(wù)微服務(wù)的跨域配置,防止多次跨域配置。
其實(shí),也可以采用在gateway網(wǎng)關(guān)服務(wù)的application.yml文件中配置的方式,如:
spring:
cloud:
gateway:
# 全局的跨域配置
globalcors:
# 解決options請(qǐng)求被攔截問(wèn)題
add-to-simple-url-handler-mapping: true
cors-configurations:
# 攔截的請(qǐng)求
'[/**]':
# 允許跨域的請(qǐng)求
#allowedOrigins: "*" # spring boot2.4以前的配置
allowedOriginPatterns: "*" # spring boot2.4以后的配置
# 允許請(qǐng)求中攜帶的頭信息
allowedHeaders: "*"
# 運(yùn)行跨域的請(qǐng)求方式
allowedMethods: "*"
# 是否允許攜帶cookie
alloweCredentials: true
# 跨域檢測(cè)的有效期,單位s
maxAge: 36000
不要出現(xiàn)重復(fù)解決跨域問(wèn)題,若之前用過(guò)注解@CrossOrigin,然后又添加了過(guò)濾器,就會(huì)導(dǎo)致重復(fù),僅用過(guò)濾器就OK了。
情況3
當(dāng)gateway網(wǎng)關(guān)服務(wù)設(shè)置了跨域,業(yè)務(wù)微服務(wù)也設(shè)置了跨域,則需要在網(wǎng)關(guān)的配置里加上重復(fù)請(qǐng)求頭,如
pring:
cloud:
gateway:
globalcors:
default-filters:
- DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Headers Access-Control-Allow-Credentials,RETAIN_UNIQUE
當(dāng)業(yè)務(wù)微服務(wù)集成了security+oauth2,會(huì)出現(xiàn)跨域失效的情況,需要在WebSecurityConfig配置類(lèi)和ResourceServerConfig配置類(lèi)中開(kāi)啟CORS,如下
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable();
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable();
}
當(dāng)gateway網(wǎng)關(guān)微服務(wù)集成了security+oauth2,又會(huì)出現(xiàn)跨域問(wèn)題,則需要在ResourceServerConfig配置類(lèi)中加入跨域過(guò)濾器,如下
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException {
http.cors().and().csrf().disable();
http.addFilterBefore(corsWebFiler, SecurityWebFiltersOrder.CORS);
}
跨域問(wèn)題:The ‘Access-Control-Allow-Origin’ header contains multiple values “*, *”, but only one is allowed.
分析:通??缬騿?wèn)題可以在三個(gè)地方解決:
- 在微服務(wù)的代碼中通過(guò)跨域配置類(lèi)解決;
- 在網(wǎng)關(guān)中解決,可以通過(guò)配置類(lèi),也可以通過(guò)yml配置;
- 在nginx或vue中解決;
以上3種方式,若使用了2種,則會(huì)出現(xiàn)雙重跨域的問(wèn)題。那么若是知道那里用了2次跨域配置,選擇去掉一個(gè)即可;若是2個(gè)地方都不想去掉,還可以在網(wǎng)關(guān)中通過(guò)yml配置來(lái)忽略掉雙重跨域的問(wèn)題。
spring:
main:
allow-bean-definition-overriding: true
gateway:
discovery: 默認(rèn)為false,設(shè)為true便開(kāi)啟通過(guò)服務(wù)中心的自動(dòng)根據(jù) serviceId 創(chuàng)建路由的功能。
locator:
enabled: true
lowerCaseServiceId: true
#解決跨域問(wèn)題
globalcors:
corsConfigurations:
'[/**]':
# 允許攜帶認(rèn)證信息
allow-credentials: true
# 允許跨域的源(網(wǎng)站域名/ip),設(shè)置*為全部
allowedOrigins: "*"
# 允許跨域的method, 默認(rèn)為GET和OPTIONS,設(shè)置*為全部
allowedMethods: "*"
# 允許跨域請(qǐng)求里的head字段,設(shè)置*為全部
allowedHeaders: "*"
#解決雙重跨域 RETAIN_FIRST RETAIN_LAST RETAIN_UNIQUE
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials Vary, RETAIN_UNIQUE
具體跨域問(wèn)題還需根據(jù)具體情況分析解決。
到此這篇關(guān)于SpringCloud微服務(wù)中跨域配置的方法詳解的文章就介紹到這了,更多相關(guān)SpringCloud跨域配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java HttpURLConnection超時(shí)和IO異常處理
這篇文章主要介紹了Java HttpURLConnection超時(shí)和IO異常處理的相關(guān)資料,需要的朋友可以參考下2016-09-09
Java語(yǔ)言中finally是否一定會(huì)執(zhí)行你知道嗎
這篇文章主要為大家詳細(xì)介紹了Java finally是否一定會(huì)執(zhí)行,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02
myBatis組件教程之緩存的實(shí)現(xiàn)與使用
這篇文章主要給大家介紹了關(guān)于myBatis組件教程之緩存的實(shí)現(xiàn)與使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11
Java開(kāi)發(fā)必備知識(shí)之?dāng)?shù)組詳解
數(shù)組對(duì)于每一門(mén)編程語(yǔ)言來(lái)說(shuō)都是重要的數(shù)據(jù)結(jié)構(gòu)之一,當(dāng)然不同語(yǔ)言對(duì)數(shù)組的實(shí)現(xiàn)及處理也不盡相同.本篇文章為大家整理了Java最全關(guān)于數(shù)組的知識(shí)點(diǎn),并給出其對(duì)應(yīng)的代碼,需要的朋友可以參考下2021-06-06
淺析SpringBoot及環(huán)境搭建過(guò)程
Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程.這篇文章主要介紹了SpringBoot介紹及環(huán)境搭建,需要的朋友可以參考下2018-01-01
Spring如何基于Proxy及cglib實(shí)現(xiàn)動(dòng)態(tài)代理
這篇文章主要介紹了Spring如何基于Proxy及cglib實(shí)現(xiàn)動(dòng)態(tài)代理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
spring注入在有常量的情況下使用@AllArgsConstructor操作
這篇文章主要介紹了spring注入在有常量的情況下使用@AllArgsConstructor操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
SpringBoot雪花算法主鍵ID傳到前端后精度丟失問(wèn)題的解決
本文主要介紹了SpringBoot雪花算法主鍵ID傳到前端后精度丟失問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08

