CORS
介绍
出于安全的考虑,浏览器禁止ajax调用当前域之外的资源。例如,当你在一个选项卡上查看你的银行账户时,你可以在另一个标签页打开evil.com网站。来自evil.com的脚本不应该能够将AJAX请求发送到您的银行API(例如:取钱操作)
跨源资源共享(CORS)是由大多数浏览器实现的W3C规范,允许您以灵活的方式指定哪些跨域请求被授权,而不是使用诸如IFRAME或JSONP之类的安全性较低的小技巧。
SpringWebflux支持CORS。CORS请求包括选项方法preflight自动注册到处理器映射器中。使用CorsProcessor实现(默认为DefaultCorsProcessor)来处理CORS的preflight请求和拦截CORS的简单和实际请求,以便根据您提供的CORS配置添加相关的CORS响应头(例如:Access-Control-Allow-Origin)
注意:cookie在任何情况下是默认不被允许的。以避免增加web攻击风险(例如,通过暴露敏感的用户特定的信息,如CSRF令牌)。将证书Credentialsproperty设置为true,允许cookie开启
@CrossOrigin
可以在@RequestMapping注释处理程序方法中添加一个@CrossOrigin注释,以便启用CORS。
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@GetMapping("/{id}")
public Mono<Account> retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public Mono<Void> remove(@PathVariable Long id) {
// ...
}
}
还可以控制整个控制器
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@GetMapping("/{id}")
public Mono<Account> retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public Mono<Void> remove(@PathVariable Long id) {
// ...
}
}
在上面的示例中,retrieve()和remove()处理方法都启用了CORS支持,当然你还可以看到如何使用@CrossOrigin属性自定义CORS配置。甚至可以同时使用控制器级和方法级的CORS配置;然后Spring将结合两个注释的属性来创建合并的CORS配置。
@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配置
除了精细的、基于注解的配置之外,您还可能需要定义一些全局的CORS配置。这类似于使用过滤器。但是可以在Spring WebFlux中声明,并结合细粒度的@CrossOrigin。默认情况下,GET, HEAD, 和POST这些方法是允许跨域的
整个应用跨域设置
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
可以简单的更改属性,并且只将该CORS配置应用到特定的路径模式:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@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);
}
}
CORS WebFilter
你可以通过内置的CorsWebFilter来应用CORS支持,这与功能端点非常类似。
要配置过滤器,您可以声明一个CorsWebFilter bean并将CorsConfigurationSource传递给它的构造函数:
@Bean
CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
你可以轻松的让GET, HEAD和POST请求通过编写
@Bean
CorsWebFilter corsFilter() {
return new CorsWebFilter(exchange -> new CorsConfiguration().applyPermitDefaultValues());
}
高级定制
CorsConfiguration允许您指定如何处理CORS请求,并且可以通过多种方式实现。
AbstractHandlerMapping#setCorsConfigurations()
允许指定映射到路径模式(比如/ api/* *)的CorsConfiguration实例的映射。子类可以提供自己的CorsConfiguration覆盖theAbstractHandlerMapping # getCorsConfiguration(Object,ServerWebExchange)方法。
处理程序可以实现CorsConfigurationSource接口,以便为每个请求提供一个CorsConfiguration实例。