What is CORS

跨域资源共享(Cross-origin resource sharing,简称CORS),用于让网页的受限资源能够被其他域名的页面访问的一种机制。通过该机制,页面能够自由地使用不同域名(cross-origin)的图片、样式、脚本、iframes以及视频。 ——维基百科

HTTP访问控制(CORS) - HTTP | MDN

跨域资源共享CORS 详解- 阮一峰的网络日志

跨域资源共享(CORS)详解

CORS

简单请求和非简单请求

只要同时满足以下两大条件,就属于简单请求:

(1)请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

(2)HTTP的头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

Spring 项目中配置 CORS

Enabling Cross Origin Requests for a RESTful Web Service | Spring

CORS support in Spring Framework | Spring

自定义过滤器

1
2
3
4
5
6
7
8
9
10
11
12
//1. 使用过滤器注册器注册
@Configuration
public class FilterRegisterConfig {

@Bean
public FilterRegistrationBean filterRegisterBean() {
FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new CorsFilter());
registrationBean.setUrlPatterns(new ArrayList<String>() {{ add("*"); }});
return registrationBean;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//2. 使用 @WebFilter 注解
@Configuration
@WebFilter(urlPatterns = "*")
public class CorsFilter implements Filter {

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:9528");
response.setHeader("Access-Control-Max-Age", "10");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Allow-Headers", "*");
filterChain.doFilter(servletRequest, servletResponse);
}
}
  • Access-Control-Allow-Methods

    该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的请求类型。

  • Access-Control-Allow-Headers

    如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在”预检”中请求的字段。

  • Access-Control-Max-Age

    该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是 10秒,即允许缓存该条回应 10 秒,在此期间,不用发出另一条预检请求。

    注意:如果设置缓存后,发现每次还是会发送 OPTIONS 请求,请检查是不是勾选了“禁止缓存”。

注解 @CrossOrigin

1
2
3
4
5
6
7
8
9
10
// 当前 Controller 中所有的方法接受跨域访问
@CrossOrigin(origins = "http://localhost:9528", maxAge = 10)
@RestController
public class CorsController {

@PostMapping("cors")
public String cors() {
return "success";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 仅 /cors 可以接受跨域访问
@RestController
public class CorsController {
@CrossOrigin(origins = "http://localhost:9528", maxAge = 10)
@PostMapping("cors")
public String cors() {
return "cors";
}

@PostMapping("cors2")
public String cors2(){
return "cors2";
}
}

实现 WebMvcConfigurer 接口

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class WebMvcConfigurerImpl implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// Error: registry.addMapping("*")
registry.addMapping("/**")
.allowedOrigins("http://localhost:9528")
.allowedMethods("*")
.allowedHeaders("*")
.maxAge(10L);
}
}

Spring Actuator 项目可使用 application.properties 来配置

Spring Boot enabling CORS by application.properties

1
2
3
4
endpoints.cors.allowed-origins=http://localhost:9528
endpoints.cors.allowed-methods=*
endpoints.cors.allowed-headers=*
endpoints.cors.max-age=10

Spring Security 项目中配置 CORS

CORS | Spring Security

Spring security CORS Filter | Stack Overflow

Spring Security 环境下 CORS 跨域失效问题

Spring Security配置cors跨域访问

CORS with Spring Boot and Spring Security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
// by default uses a Bean by the name of corsConfigurationSource
http.cors();
}

@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:9528"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setMaxAge(10L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}