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
他們的含義分别是:
- Access-Control-Allow-Methods: 真實請求允許的方法
- Access-Control-Allow-Headers: 伺服器允許使用的字段
- Access-Control-Allow-Credentials: 是否允許使用者發送、處理 cookie
- 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