SpringMvc @CrossOrigin 跨域

/ 后端 / 无站内评论 / 421浏览

为什么会存在跨域问题?

于安全原因,浏览器禁止对当前原点以外的资源进行AJAX调用。例如,当您在一个选项卡中检查您的银行帐户时,您可以在另一个选项卡中查看evil.com网站。来自evil.com的脚本不应该能够使用您的凭据向您的银行API发送AJAX请求(从您的帐户中提取资金!)。

跨源资源共享(CORS)跨域是大多数浏览器实现W3C规范,允许您以灵活的方式指定哪种跨域请求被授权,而不是使用一些安全性较低和功能较弱的黑客(如IFrame或JSONP)。

Spring Framework 4.2 GA 为CORS提供了一流的支持,为您提供了一种比典型的基于过滤器的解决方案更简单,更强大的配置方法。

Spring MVC提供了高级配置工具,如下所述。

SpringMvc支持版本

从Spring MVC 4.2 开始增加支持跨域访问

使用方法

某个方法支持跨域访问

您可以添加@RequestMapping注释的处理程序方法@CrossOrigin注释以启用CORS(默认情况下@CrossOrigin允许在@RequestMapping注释中指定的所有源和HTTP方法):

在方法上增加@CrossOrigin注解,如下:

@RestController
@RequestMapping("/account")
public class AccountController { @CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
} @DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

也可以为整个(类)控制器启用CORS(支持跨域):

@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) {
// ...
}
}

控制器和方法联合使用

在这个例子中,对于这两种方法retrieve()remove()处理程序方法都启用了CORS支持,并且您还可以看到如何使用@CrossOrigin属性自定义CORS配置

您甚至可以同时使用控制器和方法级CORS配置,然后Spring将这两个注释属性组合起来以创建合并的CORS配置。

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController { @CrossOrigin(origins = "http://domain2.com")
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
} @DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}

如果您使用的是Spring Security,请确保在Spring Security级别启用CORS,以使其能够利用在Spring MVC级别定义的配置。

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}

全局配置

除了细粒度的基于注释的配置之外,您还可能需要定义一些全局CORS配置。这与使用过滤器类似,但可以使用Spring MVC声明并与细粒度@CrossOrigin配置结合使用默认情况下,所有的起源和GETHEADPOST方法都是允许的。

JavaConfig

为整个应用程序启用CORS非常简单:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter { @Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

如果您使用的是Spring Boot,建议您只声明一个WebMvcConfigurerbean,如下所示:

@Configuration
public class MyConfiguration {
    @Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}

您可以轻松更改任何属性,以及仅将此CORS配置应用于特定的路径模式:

@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);
}

如果您使用的是Spring Security,请确保在Spring Security级别启用CORS,以使其能够利用在Spring MVC级别定义的配置。

XML名称空间

也可以使用mvc XML命名空间配置CORS 

这种最小的XML配置使CORS在/**路径模式上具有与JavaConfig相同的默认属性:

如果整个项目所有方法都可以访问,则可以这样配置
<mvc:cors>
	<mvc:mapping path="/**" />
</mvc:cors>

也可以使用自定义属性声明几个CORS映射:

<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="false"
max-age="123" /> <mvc:mapping path="/resources/**"
allowed-origins="http://domain1.com" /> </mvc:cors>

如果您使用的是Spring Security,请不要忘记在Spring Security级别启用CORS

<http>
	<!-- Default to Spring MVC's CORS configuration -->
	<cors />
	...
</http>

它是如何工作的?

CORS请求(包括使用OPTIONS方法的预检)会自动发送到HandlerMapping注册的各种服务器上它们处理CORS预检请求并通过CorsProcessor实现(默认为DefaultCorsProcessor拦截CORS简单和实际的请求,以添加相关的CORS响应头(如Access-Control-Allow-Origin)。CorsConfiguration允许您指定应该如何处理CORS请求:允许的来源,标题,方法等。可以通过多种方式提供它:

基于过滤器的CORS支持

除了上面介绍的其他方法外,Spring Framework还提供了一个CorsFilter在这种情况下,您可以例如在Spring Boot应用程序中声明过滤器,而不是使用@CrossOrigin或者WebMvcConfigurer#addCorsMappings(CorsRegistry)

@Configuration
public class MyConfiguration {
	@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}
资料整理自Spring官方:http://www.cnblogs.com/fanshuyao/p/7168471.html
召唤蕾姆
琼ICP备18000156号

鄂公网安备 42011502000211号