转载自https://www.cnblogs.com/powercto/p/6915709.html
出于安全考虑,浏览器禁止对当前源之外的资源进行AJAX调用。例如,当你在一个标签页检查你的银行账户时,你可以在另一个标签页打开evil.com的网站。在evil.com中的脚本不能使用你的凭据来通过AJAX请求访问你的银行API(例如,从你的银行取款!)。
跨域资源共享(Cross-origin resource sharing)(CORS)是W3C的标准,大部分的浏览器都实现了这个标准来让你可以灵活地指定什么样的跨域请求是被授权的,而不用使用IFRAME或JSONP这些不太安全和功能不强的黑客技术。
从Spring Framework 4.2起,CORS就支持开箱即用。CORS请求(包括一个预检请求OPTIONS方法)自动分发到各个注册的HandlerMapping中。由于CorsProcessor的实现(默认是DefaultCorsProcessor),它们处理CORS预检请求,并拦截CORS的简单而实际请求,以便根据你提供的CORS配置添加相关的CORS响应头(如Access-Control-Allow-Origin)。
由于CORS请求是自动分发的,你不需要改变DispatcherServlet dispatchOptionsRequest的初始参数值;推荐的方式是使用它的默认值(false)。
你可以在你的@RequestMapping注解处理方法上添加一个@CrossOrigin注解来开启CORS。默认@CrossOrigin允许所有的源和在@RequestMapping注解上指定的HTTP方法:
@RestController
@RequestMapping(“/account”)
public class AccountController {
@CrossOrigin
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
它也可以在所有的控制器上开启CORS:
@CrossOrigin(origins = “http://domain2.com“, maxAge = 3600)
@RestController
@RequestMapping(“/account”)
public class AccountController {
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public 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")
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
除了基于注解的细粒度配置,你也可能想要定义一些全局的CORS配置。这个与使用过滤器类似,但是可以在Spring MVC中声明跟加上@CrossOrigin的细粒度配置。默认是允许所有的源跟GET,HEAD和POST方法。
例子如下:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
你可以轻松地改变任何属性,也可以将CORS配置指定到特殊的路径模式:
@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(false).maxAge(3600);
}
}
CorsConfiguration允许你指定CORS请求如何被处理:允许的源,头信息,方法等等。它可以以多种方式提供:
AbstractHandlerMapping#setCorsConfiguration()允许通过一个有一些CorsConfiguration实例的Map来指定映射到如/api/**的路径模式上。
子类也可以通过重写AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)方法来提供它们的CorsConfiguration。
为了给每个请求提供一个CorsConfiguration实例,处理器可以实现CorsConfigurationSource接口(如ResourceHttpRequestHandler现在做的)。
基于过滤器的CORS支持
为了实现如Spring Security的基于过滤器的安全框架去支持CORS,或其他原生不支持CORS的类库,Spring框架也提供了CorsFilter。而不是使用@CrossOrigin或WebMvcConfigurer#addCorsMappings(CorsRegistry),你需要注册一个如下的自定义过滤器:
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
public class MyCorsFilter extends CorsFilter {
public MyCorsFilter() {
super(configurationSource());
}
private static UrlBasedCorsConfigurationSource configurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
你需要确保CorsFilter在其他过滤器之前