在框架4.2版本后,Spring给出了注解的方式解决问题。
即在Controller控制器中,在Controller注解上方添加@CrossOrigin注解。
但是使用这种方式后也有可能仍然出现跨域问题,解决方案之一就是:
在@RequestMapping注解中没有指定Get、Post方式
如果想要对某一接口配置 CORS,可以在方法上添加 CrossOrigin 注解:
@CrossOrigin(origins = {"http://localhost:9000", "null"})@RequestMapping(value = "/test", method = RequestMethod.GET)public String greetings() { return "{\"project\":\"just a test\"}";}
第二种情况,如果想对一系列接口添加 CORS 配置,可以在类上添加注解,对该类声明所有接口都有效:
CrossOrigin(origins = {"http://localhost:9000", "null"})@RestController@SpringBootApplicationpublic class SpringBootCorsTestApplication { // xxx}
第三种情况,添加全局配置,则需要添加一个配置类:
@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:9000", "null") .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") .maxAge(3600) .allowCredentials(true); }}
另外,还可以通过添加 Filter 的方式,配置 CORS 规则,并手动指定对哪些接口有效。
@Beanpublic FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://localhost:9000"); config.addAllowedOrigin("null"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); // CORS 配置对所有接口都有效 FilterRegistrationBean bean = newFilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); return bean;}
4. 实现剖析
无论是通过哪种方式配置 CORS,其实都是在构造 CorsConfiguration。
一个 CORS 配置用一个CorsConfiguration
类来表示,它的定义如下: public class CorsConfiguration { private ListallowedOrigins; private List allowedMethods; private List allowedHeaders; private List exposedHeaders; private Boolean allowCredentials; private Long maxAge;}
Spring MVC 中对 CORS 规则的校验,都是通过委托给 DefaultCorsProcessor 实现的。
DefaultCorsProcessor 处理过程如下:
- 判断依据是 Header 中是否包含 Origin。如果包含则说明为 CORS 请求,转到 2;否则,说明不是 CORS 请求,不作任何处理。
- 判断 response 的 Header 是否已经包含 Access-Control-Allow-Origin,如果包含,证明已经被处理过了, 转到 3,否则不再处理。
- 判断是否同源,如果是则转交给负责该请求的类处理
- 是否配置了 CORS 规则,如果没有配置,且是预检请求,则拒绝该请求,如果没有配置,且不是预检请求,则交给负责该请求的类处理。如果配置了,则对该请求进行校验。
校验就是根据 CorsConfiguration 这个类的配置进行判断:
- 判断 origin 是否合法
- 判断 method 是否合法
- 判断 header 是否合法
- 如果全部合法,则在 response header 中添加响应的字段,并交给负责该请求的类处理,如果不合法,则拒绝该请求。