spring数据rest和Cors
我正在开发一个Rest接口和一个DART前端的Spring Boot应用程序。
XMLHttpRequest确实执行完全正确的OPTIONS请求。 在此之后,最后的GET(“/ products”)请求被发出并失败:
请求的资源上没有“Access-Control-Allow-Origin”标题。 原因' http:// localhost:63343 '因此不被允许访问。
经过一些debugging后,我发现了以下内容:AbstractHandlerMapping.corsConfiguration为除RepositoryRestHandlerMapping之外的所有子类填充。 在RepositoryRestHandlerMapping中,在创build时不存在/设置corsConfiguration,所以它不会被识别为corspath/资源。
=>没有附加CORS头文件
这可能是问题吗? 我该如何设置?
configuration类:
@Configuration public class RestConfiguration extends RepositoryRestMvcConfiguration { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowCredentials(false).allowedOrigins("*").allowedMethods("PUT", "POST", "GET", "OPTIONS", "DELETE").exposedHeaders("Authorization", "Content-Type"); } ... }
我甚至试图设置Cors每个注释:
@CrossOrigin( methods = RequestMethod.GET, allowCredentials = "false") public interface ProductRepository extends CrudRepository<Product, String> { }
原始请求标题:
GET /products HTTP/1.1 Host: localhost:8080 Connection: keep-alive Cache-Control: max-age=0 authorization: Basic dXNlcjpwYXNzd29yZA== User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/43.0.2357.130 Chrome/43.0.2357.130 Safari/537.36 Content-Type: application/json Accept: */* Referer: http://localhost:63343/inventory-web/web/index.html Accept-Encoding: gzip, deflate, sdch Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
原始响应标题:
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: application/hal+json;charset=UTF-8 Transfer-Encoding: chunked Date: Thu, 30 Jul 2015 15:58:03 GMT
使用的版本:Spring Boot 1.3.0.M2 Spring 4.2.0.RC2
我错过了什么?
事实上,在Spring Data REST 2.6(Ingalls)之前,Spring MVC WebMvcConfigurationSupport
创build的HandlerMapping
实例和使用@CrossOrigin
注解的控制器是CORS感知的。
但是现在DATAREST-573已经修复了, RepositoryRestConfiguration
现在公开了一个用于全局设置的getCorsRegistry()
,并且库中的@CrossOrigin
注解也被识别,所以这是推荐的方法。 有关具体示例,请参阅https://stackoverflow.com/a/42403956/1092077答案。;
对于那些不得不坚持Spring Data REST 2.5(Hopper)或以前版本的人来说,我认为最好的解决scheme是使用基于filter的方法。 你可以明显地使用Tomcat,Jetty或者这个 ,但是请注意,Spring Framework 4.2还提供了一个CorsFilter
,它使用了@CrossOrigin
和addCorsMappings(CorsRegistry registry)
的相同的CORS处理逻辑。 通过将UrlBasedCorsConfigurationSource
实例传递给CorsFilter
构造函数参数,您可以轻松获得与Spring本地CORS全局支持一样强大的function。
如果你使用的是Spring Boot(它支持Filter
bean),它可能是这样的:
@Configuration public class RestConfiguration { @Bean public FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); return bean; } }
由于Ingalls的培训已经实现 ,CORS在Spring Data的支持已经到来。 有两种方法可以处理:
-
通过
@CrossOrigin
接口指定@CrossOrigin
,methods
和allowedHeaders
的@CrossOrigin
注释。@CrossOrigin(...) @RepositoryRestResource public interface PageRepository extends CrudRepository<Page, Long> { ... }
-
在
@Configuration
类中使用RepositoryRestConfiguration
全局configuration。 然后用@CrossOrigin
标记存储库是没有必要的。@Configuration public class GlobalRepositoryRestConfigurer extends RepositoryRestConfigurerAdapter { @Override public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.getCorsRegistry() .addMapping(CORS_BASE_PATTERN) .allowedOrigins(ALLOWED_ORIGINS) .allowedHeaders(ALLOWED_HEADERS) .allowedMethods(ALLOWED_METHODS); } }
由于某种原因,上面接受的答案中提出的方法在从Spring Boot 1.5.2升级到1.5.6之后对我无效。
正如@ BigDong的评论所指出的,我得到的例外是:
BeanInstantiationException:无法实例化[javax.servlet.Filter]:工厂方法'springSecurityFilterChain'抛出exception; 嵌套的exception是org.springframework.beans.factory.BeanNotOfRequiredTypeExcep tion:Bean名为'corsFilter'预计是'org.springframework.web.filter.CorsFilter'types,但实际上是types'org.springframework.boot.web .servlet.FilterRegistrationBean
因此,我想到了在REST API中为所有端点获得“全局”CORSconfiguration,无论它们是使用Spring Data Rest还是Spring MVC实现的,所有端点都受到Spring Security的保护。
我无法在正确的位置将CorsFilter
到请求pipe道中,因此我分别configuration了SDR和MVC,但是通过此帮助程序为其CorsRegistry
使用相同的configuration:
public static void applyFullCorsAllowedPolicy(CorsRegistry registry) { registry.addMapping("/**") // .allowedOrigins("*") // .allowedMethods("OPTIONS", "HEAD", "GET", "PUT", "POST", "DELETE", "PATCH") // .allowedHeaders("*") // .exposedHeaders("WWW-Authenticate") // .allowCredentials(true) .maxAge(TimeUnit.DAYS.toSeconds(1)); }
然后对于MVC:
@Configuration @EnableWebSecurity(debug = true) @EnableGlobalMethodSecurity(prePostEnabled = true) public class CustomWebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // enables CORS as per // https://docs.spring.io/spring-security/site/docs/current/reference/html/cors.html#cors http.cors() .and() // ... } @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { applyFullCorsAllowedPolicy(registry); } }; } }
然后对于SDR:
public class CustomRepositoryRestMvcConfiguration extends RepositoryRestConfigurerAdapter { @Override public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.setReturnBodyOnCreate(true); config.setReturnBodyForPutAndPost(true); config.setReturnBodyOnUpdate(true); config.setMaxPageSize(250); config.setDefaultPageSize(50); config.setDefaultMediaType(MediaTypes.HAL_JSON); config.useHalAsDefaultJsonMediaType(true); CustomWebSecurityConfiguration.applyFullCorsAllowedPolicy(config.getCorsRegistry()); }
这里有一些关于这个问题的进一步的参考,帮助我想出了这个答案: