Spring处理跨域请求

@CrossOrigin 注解

@CrossOrigin 注解在控制器方法上启用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping("/account")
public class AccountController {

@CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}

@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

默认的 @CrossOrigin 启用以下功能:

  • All origins.所有请求源,向该服务器提交请求的URI
  • All headers.全部的访问头信息
  • All HTTP methods to which the controller method is mapped.控制器方法映射到的所有HTTP方法。
  • allowedCredentials is not enabled by default since that establishes a trust level that exposes sensitive user-specific information such as cookies and CSRF tokens, and should only be used where appropriate.allowedCredentials默认情况下未启用,因为它建立了一个信任级别,用于公开敏感的用户特定信息,如Cookie和CSRF令牌,并且只能在适当的情况下使用。
  • maxAge is set to 30 minutes.maxAge设置为30分钟。预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了

@CrossOrigin 也在类级别上得到支持,并由所有方法继承:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}

@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

@CrossOrigin 可以在类和方法同时使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

@CrossOrigin("http://domain2.com")
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}

@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

全局配置

Java配置

要在MVC Java配置中启用CORS,请使用CorsRegistry回调:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {

registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(true).maxAge(3600);

// Add more mappings...
}
}

XML配置

要在XML命名空间中启用CORS,使用 <mvc:cors> 元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
<mvc:cors>

<mvc:mapping path="/api/**"
allowed-origins="http://domain1.com, http://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="true"
max-age="123" />

<mvc:mapping path="/resources/**"
allowed-origins="http://domain1.com" />

</mvc:cors>

CORS过滤器

可以通过内置的CorsFilter来应用CORS支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class CorsConfig {

@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 允许cookies跨域
config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
config.addAllowedHeader("*");// #允许访问的头信息,*表示全部
config.setMaxAge(3600L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
config.addAllowedMethod("*");// 允许提交请求的方法,*表示全部允许
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

其他

  • 使用jsonp来进行跨域,但不太安全。
  • 后台response添加header,response.setHeader("Access-Control-Allow-Origin", "*");
1
2
3
4
5
6
7
8
9
10
11
@Controller  
public static class TestController {
@RequestMapping(value = "/test")
@ResponseBody
public String getInfo(String id, HttpServletResponse response)
throws Exception {
response.setHeader("Access-Control-Allow-Origin", "*");
//.......
return ".....";
}
}

参考资料