相关推荐recommended
Spring CORS 跨域使用与原理(@CrossOrigin注解,Java配置类方式,xml方式)
作者:mmseoamin日期:2023-12-21

Spring CORS 跨域使用与原理(@CrossOrigin注解,Java配置类方式,xml方式)

出于安全原因,浏览器禁止AJAX调用当前源之外的资源。

跨域资源共享(CORS)是由大多数浏览器实现的W3C规范,它允许您以一种灵活的方式指定授权哪种跨域请求,而不是使用一些不太安全、功能不太强大的hack(如IFrame或JSONP)。

Spring Framework 4.2 GA为CORS提供了一流的开箱即用支持,为我们提供了一种比典型的基于过滤器的解决方案更简单、更强大的配置方式。

一、注解方式使用

1.方法上添加@CrossOrigin注解
@RestController
@RequestMapping("/account")
public class AccountController {
	@CrossOrigin
	@GetMapping("/{id}")
	public Account retrieve(@PathVariable Long id) {
		// ...
	}
	@DeleteMapping("/{id}")
	public void remove(@PathVariable Long id) {
		// ...
	}
}

使用此种方式只会对当前方法生效。

2.Controller上添加@CrossOrigin注解
@CrossOrigin
@RestController
@RequestMapping("/account")
public class AccountController {
	@GetMapping("/{id}")
	public Account retrieve(@PathVariable Long id) {
		// ...
	}
	@DeleteMapping("/{id}")
	public void remove(@PathVariable Long id) {
		// ...
	}
}

使用此种方式会对整个Controller生效。

3.@CrossOrigin的两个参数使用
  1. origins: 允许可访问的域列表
  2. maxAge:准备响应前的缓存持续的最大时间(以秒为单位)
@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(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) {
		// ...
	}
}
4.注意事项

如果有正在使用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全局配置使用

除了细粒度的、基于注释的配置之外,我们还可以自定义一些全局CORS配置。类似于使用过滤器,但可以在Spring MVC中声明,并结合细粒度的@CrossOrigin配置。默认情况下,所有的origin和GET、HEAD和POST方法都可以使用。

1.Java配置类方式

使用非常简单,如下所示:

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

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

@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使用的情况,具体实现参考注解使用中的实现。

2.XML配置文件方式

当然,我们也可以使用xml配置文件的方式来进行全局配置,如下所示:


	

同样也可以在xml中自定义CORS映射,如下所示:


	
	

如果正在使用Spring Security,同样要在Spring Security启用CORS:


	
	
	...

三、原理解释

CORS请求(包括带有OPTIONS方法的飞行前请求)被自动分派给已注册的各种HandlerMappings。它们处理CORS预飞行请求,并通过CorsProcessor实现(默认为DefaultCorsProcessor)拦截CORS简单和实际请求,以便添加相关的CORS响应头(如Access-Control-Allow-Origin)。CorsConfiguration允许您指定应该如何处理CORS请求:allowed origins, headers, methods, etc等。

可以通过多种方式提供,如:

  • AbstractHandlerMapping#setCorsConfiguration()允许在路径模式(如/api/)上指定多个CorsConfiguration映射的Map
  • 子类可以通过重写AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)方法来提供他们自己的CorsConfiguration
  • 处理程序可以实现CorsConfigurationSource接口(就像ResourceHttpRequestHandler现在做的那样),以便为每个请求提供CorsConfiguration。

    除此之外,还可以使用基于CORS的过滤器支持,作为上述其他方法的替代方案,Spring Framework还提供了CorsFilter。在这种情况下,不使用@CrossOrigin或WebMvcConfigurer# addcorsmapping (CorsRegistry),我们可以像下面这样在Spring Boot中声明过滤器:

    @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官方文档:https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

    同时欢迎各位来我的个人博客:http://bravegougou.cn/