SpringBoot 跨域問(wèn)題的解決方案
什么是跨域?
定義:瀏覽器從一個(gè)域名的網(wǎng)頁(yè)取請(qǐng)求另一個(gè)域名下的東西。通俗點(diǎn)說(shuō),瀏覽器直接從A域訪問(wèn)B域中的資源是不被允許的,如果想要訪問(wèn),就需要進(jìn)行一步操作,這操作就叫“跨域”。例如,你從百度的頁(yè)面,點(diǎn)擊一個(gè)按鈕,請(qǐng)求了新浪的一個(gè)接口,這就進(jìn)行了跨域。不單單只有域名不同就是跨域,域名、端口、協(xié)議其一不同就是不同的域,請(qǐng)求資源需要跨域。
為什么要跨域?
為什么需要跨域,而不直接訪問(wèn)其他域下的資源呢?這是瀏覽器的限制,專業(yè)點(diǎn)說(shuō)叫瀏覽器同源策略限制。主要是為了安全考慮。現(xiàn)在的安全框架,一般請(qǐng)求的時(shí)候header中不是都存?zhèn)€token嘛,你要是用這個(gè)token去正常訪問(wèn)A域下的東西是沒(méi)問(wèn)題的,然后又去訪問(wèn)了B域,結(jié)果陰差陽(yáng)錯(cuò)的還帶著這個(gè)token,那么B域,或者說(shuō)B網(wǎng)站是不是就可以拿著你的token去A域下做點(diǎn)什么呢,這就相當(dāng)危險(xiǎn)了。所以瀏覽器加上了所謂的瀏覽器同源策略限制。但是為了我們真的需要從A域下訪問(wèn)B的資源(正常訪問(wèn)),就需要用到跨域,跨越這個(gè)限制了。
SpringBoot解決跨域問(wèn)題
SpringBoot可以基于Cors解決跨域問(wèn)題,Cors是一種機(jī)制,告訴我們的后臺(tái),哪邊(origin )來(lái)的請(qǐng)求可以訪問(wèn)服務(wù)器的數(shù)據(jù)。
全局配置
配置實(shí)例如下:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
}
首先實(shí)現(xiàn)了WebMvcConfigurer 接口,WebMvcConfigurer 這個(gè)接口十分強(qiáng)大,里面還有很多可用的方法,在SpringBoot2.0里面可以解決WebMvcConfigurerAdapter曾經(jīng)的部分任務(wù)。其中一個(gè)方法就是addCorsMappings(),是專門為開(kāi)發(fā)人員解決跨域而誕生的接口。其中構(gòu)造參數(shù)為CorsRegistry。
看下CorsRegistry源碼,十分簡(jiǎn)單:
public class CorsRegistry {
private final List<CorsRegistration> registrations = new ArrayList<>();
public CorsRegistration addMapping(String pathPattern) {
CorsRegistration registration = new CorsRegistration(pathPattern);
this.registrations.add(registration);
return registration;
}
protected Map<String, CorsConfiguration> getCorsConfigurations() {
Map<String, CorsConfiguration> configs = new LinkedHashMap<>(this.registrations.size());
for (CorsRegistration registration : this.registrations) {
configs.put(registration.getPathPattern(), registration.getCorsConfiguration());
}
return configs;
}
}
可以看出CorsRegistry 有個(gè)屬性registrations ,按道理可以根據(jù)不同的項(xiàng)目路徑進(jìn)行定制訪問(wèn)行為,但是我們示例直接將pathPattern 設(shè)置為 /**,也就是說(shuō)已覆蓋項(xiàng)目所有路徑,只需要?jiǎng)?chuàng)建一個(gè)CorsRegistration就好。getCorsConfigurations(),這個(gè)方法是獲取所有CorsConfiguration的Map集合,key值為傳入路徑pathPattern。
回到示例代碼CorsConfig中,registry對(duì)象addMapping()增加完傳入路徑pathPattern之后,return了一個(gè)CorsRegistration對(duì)象,是進(jìn)行更多的配置,看一下CorsRegistration的代碼,看看我們能配些什么?
public class CorsRegistration {
//傳入的路徑
private final String pathPattern;
//配置信息實(shí)體類
private final CorsConfiguration config;
//構(gòu)造方法
public CorsRegistration(String pathPattern) {
this.pathPattern = pathPattern;
//原生注釋看到了一個(gè) @CrossOrigin 這個(gè)注解,待會(huì)看看是什么
// Same implicit default values as the @CrossOrigin annotation + allows simple methods
this.config = new CorsConfiguration().applyPermitDefaultValues();
}
//允許哪些源網(wǎng)站訪問(wèn),默認(rèn)所有
public CorsRegistration allowedOrigins(String... origins) {
this.config.setAllowedOrigins(Arrays.asList(origins));
return this;
}
//允許何種方式訪問(wèn),默認(rèn)簡(jiǎn)單方式,即:GET,HEAD,POST
public CorsRegistration allowedMethods(String... methods) {
this.config.setAllowedMethods(Arrays.asList(methods));
return this;
}
//設(shè)置訪問(wèn)header,默認(rèn)所有
public CorsRegistration allowedHeaders(String... headers) {
this.config.setAllowedHeaders(Arrays.asList(headers));
return this;
}
//設(shè)置response headers,默認(rèn)沒(méi)有(什么都不設(shè)置)
public CorsRegistration exposedHeaders(String... headers) {
this.config.setExposedHeaders(Arrays.asList(headers));
return this;
}
//是否瀏覽器應(yīng)該發(fā)送credentials,例如cookies Access-Control-Allow-Credentials
public CorsRegistration allowCredentials(boolean allowCredentials) {
this.config.setAllowCredentials(allowCredentials);
return this;
}
//設(shè)置等待時(shí)間,默認(rèn)1800秒
public CorsRegistration maxAge(long maxAge) {
this.config.setMaxAge(maxAge);
return this;
}
protected String getPathPattern() {
return this.pathPattern;
}
protected CorsConfiguration getCorsConfiguration() {
return this.config;
}
}
局部配置
剛才遇到一個(gè)@CrossOrigin這個(gè)注解,看看它是干什么的?
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ORIGINS = { "*" };
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ALLOWED_HEADERS = { "*" };
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
boolean DEFAULT_ALLOW_CREDENTIALS = false;
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
long DEFAULT_MAX_AGE = 1800
/**
* Alias for {@link #origins}.
*/
@AliasFor("origins")
String[] value() default {};
@AliasFor("value")
String[] origins() default {};
String[] allowedHeaders() default {};
String[] exposedHeaders() default {};
RequestMethod[] methods() default {};
String allowCredentials() default "";
long maxAge() default -1;
}
這個(gè)注解可以作用于方法或者類上,實(shí)現(xiàn)局部跨域,你會(huì)發(fā)現(xiàn)除了設(shè)置路徑(因?yàn)闆](méi)必要了,都定位到局部了)其他的參數(shù)與全局類似。
小結(jié)
SpringBoot可以基于Cors解決跨域問(wèn)題,可以設(shè)置全局跨域,也可以實(shí)現(xiàn)局部跨域,靈活配置方便使用。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java 非對(duì)稱加密算法DH實(shí)現(xiàn)詳解
這篇文章主要介紹了java 非對(duì)稱加密算法DH實(shí)現(xiàn)詳解 ,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
SpringMVC KindEditor在線編輯器之文件上傳代碼實(shí)例
這篇文章主要介紹了SpringMVC KindEditor在線編輯器之文件上傳代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
mybatis plus saveOrUpdate實(shí)現(xiàn)有重復(fù)數(shù)據(jù)就更新,否則新增方式
這篇文章主要介紹了mybatis plus saveOrUpdate實(shí)現(xiàn)有重復(fù)數(shù)據(jù)就更新,否則新增方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Java網(wǎng)絡(luò)編程UDP實(shí)現(xiàn)多線程在線聊天
這篇文章主要為大家詳細(xì)介紹了Java網(wǎng)絡(luò)編程UDP實(shí)現(xiàn)多線程在線聊天,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
SpringBoot遇到的坑@Qualifier報(bào)紅的解決
這篇文章主要介紹了SpringBoot遇到的坑@Qualifier報(bào)紅的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Spring boot測(cè)試找不到SpringRunner.class的問(wèn)題
這篇文章主要介紹了Spring boot測(cè)試找不到SpringRunner.class的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01

