天天看點

跨域問題與SpringBoot解決方案

跨域問題與SpringBoot解決方案

什麼是跨域?

定義:浏覽器從一個域名的網頁取請求另一個域名下的東西。通俗點說,浏覽器直接從A域通路B域中的資源是不被允許的,如果想要通路,就需要進行一步操作,這操作就叫“跨域”。例如,你從百度的頁面,點選一個按鈕,請求了新浪的一個接口,這就進行了跨域。不單單隻有域名不同就是跨域,域名、端口、協定其一不同就是不同的域,請求資源需要跨域。

為什麼要跨域?

為什麼需要跨域,而不直接通路其他域下的資源呢?這是浏覽器的限制,專業點說叫浏覽器同源政策限制。主要是為了安全考慮。現在的安全架構,一般請求的時候header中不是都存個token嘛,你要是用這個token去正常通路A域下的東西是沒問題的,然後又去通路了B域,結果陰差陽錯的還帶着這個token,那麼B域,或者說B網站是不是就可以拿着你的token去A域下做點什麼呢,這就相當危險了。是以浏覽器加上了所謂的浏覽器同源政策限制。但是為了我們真的需要從A域下通路B的資源(正常通路),就需要用到跨域,跨越這個限制了。

SpringBoot解決跨域問題

SpringBoot可以基于Cors解決跨域問題,Cors是一種機制,告訴我們的背景,哪邊(origin )來的請求可以通路伺服器的資料。

全局配置

配置執行個體如下:

@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);
}           

}

首先實作了WebMvcConfigurer 接口,WebMvcConfigurer 這個接口十分強大,裡面還有很多可用的方法,在SpringBoot2.0裡面可以解決WebMvcConfigurerAdapter曾經的部分任務。其中一個方法就是addCorsMappings(),是專門為開發人員解決跨域而誕生的接口。其中構造參數為CorsRegistry。

看下CorsRegistry源碼,十分簡單:

public class CorsRegistry {

private final List registrations = new ArrayList<>();

public CorsRegistration addMapping(String pathPattern) {

CorsRegistration registration = new CorsRegistration(pathPattern);
  this.registrations.add(registration);
  return registration;           

protected Map getCorsConfigurations() {

Map<String, CorsConfiguration> configs = new LinkedHashMap<>(this.registrations.size());
  for (CorsRegistration registration : this.registrations) {
     configs.put(registration.getPathPattern(), registration.getCorsConfiguration());
  }
  return configs;           

}

可以看出CorsRegistry 有個屬性registrations ,按道理可以根據不同的項目路徑進行定制通路行為,但是我們示例直接将pathPattern 設定為 /**,也就是說已覆寫項目所有路徑,隻需要建立一個CorsRegistration就好。getCorsConfigurations(),這個方法是擷取所有CorsConfiguration的Map集合,key值為傳入路徑pathPattern。

回到示例代碼CorsConfig中,registry對象addMapping()增加完傳入路徑pathPattern之後,return了一個CorsRegistration對象,是進行更多的配置,看一下CorsRegistration的代碼,看看我們能配些什麼?

public class CorsRegistration {

//傳入的路徑           

private final String pathPattern;

//配置資訊實體類           

private final CorsConfiguration config;

//構造方法           

public CorsRegistration(String pathPattern) {

this.pathPattern = pathPattern;
  //原生注釋看到了一個 @CrossOrigin 這個注解,待會看看是什麼
  // Same implicit default values as the @CrossOrigin annotation + allows simple methods
  this.config = new CorsConfiguration().applyPermitDefaultValues();           
//允許哪些源網站通路,預設所有           

public CorsRegistration allowedOrigins(String... origins) {

this.config.setAllowedOrigins(Arrays.asList(origins));
  return this;           
//允許何種方式通路,預設簡單方式,即:GET,HEAD,POST           

public CorsRegistration allowedMethods(String... methods) {

this.config.setAllowedMethods(Arrays.asList(methods));
  return this;           
//設定通路header,預設所有           

public CorsRegistration allowedHeaders(String... headers) {

this.config.setAllowedHeaders(Arrays.asList(headers));
  return this;           
//設定response headers,預設沒有(什麼都不設定)           

public CorsRegistration exposedHeaders(String... headers) {

this.config.setExposedHeaders(Arrays.asList(headers));
  return this;           
//是否浏覽器應該發送credentials,例如cookies Access-Control-Allow-Credentials           

public CorsRegistration allowCredentials(boolean allowCredentials) {

this.config.setAllowCredentials(allowCredentials);
  return this;           
//設定等待時間,預設1800秒           

public CorsRegistration maxAge(long maxAge) {

this.config.setMaxAge(maxAge);
  return this;           

protected String getPathPattern() {

return this.pathPattern;           

protected CorsConfiguration getCorsConfiguration() {

return this.config;           

局部配置

剛才遇到一個@CrossOrigin這個注解,看看它是幹什麼的?

@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 = { "*" };

String[] DEFAULT_ALLOWED_HEADERS = { "*" };

boolean DEFAULT_ALLOW_CREDENTIALS = false;

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;

這個注解可以作用于方法或者類上,實作局部跨域,你會發現除了設定路徑(因為沒必要了,都定位到局部了)其他的參數與全局類似。

小結

SpringBoot可以基于Cors解決跨域問題,可以設定全局跨域,也可以實作局部跨域,靈活配置友善使用。

跨域問題與SpringBoot解決方案

作者:Java_No2

來源:CSDN

原文:

https://blog.csdn.net/Java_No2/article/details/91612669

版權聲明:本文為部落客原創文章,轉載請附上博文連結!

繼續閱讀