天天看點

Spring boot + Spring security 跨域配置Springboot解決跨域Spring security 跨域問題

CORS 簡介

為了解決浏覽器同源問題,

W3C

 提出了跨源資源共享,即 

CORS

(Cross-Origin Resource Sharing)。

CORS

 做到了如下兩點:

  • 不破壞即有規則
  • 伺服器實作了 

    CORS

     接口,就可以跨源通信
Access-Control-Allow-Origin: http://www.examples.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
           

他們的含義分别是:

  1. Access-Control-Allow-Methods: 真實請求允許的方法
  2. Access-Control-Allow-Headers: 伺服器允許使用的字段
  3. Access-Control-Allow-Credentials: 是否允許使用者發送、處理 cookie
  4. Access-Control-Max-Age: 預檢請求的有效期,機關為秒。有效期内,不會重複發送預檢請求

當預檢請求通過後,浏覽器會發送真實請求到伺服器。這就實作了跨源請求。

Springboot解決跨域

1.CorsFilter(全局跨域)

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加CORS配置資訊
        CorsConfiguration config =new CorsConfiguration();
          //放行哪些原始域
          config.addAllowedOrigin("*");
          //是否發送Cookie資訊
          config.setAllowCredentials(true);
          //放行哪些原始域(請求方式)
          config.addAllowedMethod("*");
          //放行哪些原始域(頭部資訊
          config.addAllowedHeader("*");
          //暴露哪些頭部資訊(因為跨域通路預設不能擷取全部頭部資訊)
          config.addExposedHeader("*");
 
        //2.添加映射路徑
        UrlBasedCorsConfigurationSource configSource =new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
 
        //3.傳回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}
           

2.重寫WebMvcConfigurer(全局跨域)

//springboot 1.5方式
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
 
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**").allowedHeaders("*")
      .allowedMethods("*")
      .allowedOrigins("*")
      .allowCredentials(true);
  }
}

//springboot 2.0以上的方式
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
                .allowedMethods("*")
                .allowedOrigins("*")
                .allowCredentials(true);
    }
}
           

3.使用注解@CrossOrigin(局部跨域)

@CrossOrigin源碼

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {

    String[] DEFAULT_ORIGINS = { "*" };

    String[] DEFAULT_ALLOWED_HEADERS = { "*" };

    boolean DEFAULT_ALLOW_CREDENTIALS = true;

    long DEFAULT_MAX_AGE = 1800;


    /**
     * 同origins屬性一樣
     */
    @AliasFor("origins")
    String[] value() default {};

    /**
     * 所有支援域的集合,例如"http://domain1.com"。
     * <p>這些值都顯示在請求頭中的Access-Control-Allow-Origin
     * "*"代表所有域的請求都支援
     * <p>如果沒有定義,所有請求的域都支援
     * @see #value
     */
    @AliasFor("value")
    String[] origins() default {};

    /**
     * 允許請求頭重的header,預設都支援
     */
    String[] allowedHeaders() default {};

    /**
     * 響應頭中允許通路的header,預設為空
     */
    String[] exposedHeaders() default {};

    /**
     * 請求支援的方法,例如"{RequestMethod.GET, RequestMethod.POST}"}。
     * 預設支援RequestMapping中設定的方法
     */
    RequestMethod[] methods() default {};

    /**
     * 是否允許cookie随請求發送,使用時必須指定具體的域
     */
    String allowCredentials() default "";

    /**
     * 預請求的結果的有效期,預設30分鐘
     */
    long maxAge() default -1;
}
           

Spring security 跨域問題

使用上面方法在繼承spring security時可以會出現失效的情況,解決辦法如下,根據情況使用

方式1

SecurityConfig中配置開啟CORS

@Override
    protected void configure(HttpSecurity http) throws Exception {
        // 允許跨域通路
        http.cors();
    }
           

預設會找name為corsConfigurationSource的bean

@Bean
pubilc CorsConfigurationSource CorsConfigurationSource() {
        CorsConfigurationSource source =   new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");	//同源配置,*表示任何請求都視為同源,若需指定ip和端口可以改為如“localhost:8080”,多個以“,”分隔;
        corsConfiguration.addAllowedHeader("*");//header,允許哪些header,本案中使用的是token,此處可将*替換為token;
        corsConfiguration.addAllowedMethod("*");	//允許的請求方法,PSOT、GET等
        ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**",corsConfiguration); //配置允許跨域通路的url
        return source;
    }
           

方式2

使用spring security以前版本沒有http.cors,在security配置中新增過濾器,注意過濾器順序

http.addFilterBefore(customCorsFilter, UsernamePasswordAuthenticationFilter.class);
           

customCorsFilter為過濾器,使用spring boot中第一種解決方案的過濾器即可

spring secret:https://docs.spring.io/spring-security/site/docs

繼續閱讀