Spring 数据休息和Cors
Spring Data Rest and Cors
我正在开发一个 Spring 带有 Rest 界面和前端 dart 的启动应用程序。
XMLHttpRequest 确实执行了一个完全正确处理的 OPTIONS 请求。在此之后,发出最终的 GET ("/products") 请求并失败:
请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源“http://localhost:63343”。
经过一些调试,我发现了以下内容:
AbstractHandlerMapping.corsConfiguration 为除 RepositoryRestHandlerMapping 之外的所有 Sub类 填充。在 RepositoryRestHandlerMapping 中,在创建时不存在/设置 corsConfiguration,因此它不会被识别为 cors 路径/资源。
=> 没有 CORS header 附加
这可能是问题所在吗?我该如何设置它?
配置类:
@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> {
}
原始请求 headers:
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
原始响应 headers:
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 引导 1.3.0.M2
Spring4.2.0.RC2
我错过了什么?
确实,在 Spring Data REST 2.6 (Ingalls) 之前,只有 HandlerMapping
个由 Spring MVC WebMvcConfigurationSupport
创建的实例和用 @CrossOrigin
注释的控制器是 CORS意识到。
但是现在 DATAREST-573 has been fixed, RepositoryRestConfiguration
now exposes a getCorsRegistry()
for global setup and @CrossOrigin
annotations on repositories are also recognized so this is the recommended approach. See 回答了具体的例子。
对于必须坚持使用 Spring Data REST 2.5 (Hopper) 或以前版本的人,我认为最好的解决方案是使用基于过滤器的方法。您显然可以将 Tomcat、Jetty 或 this one, but be aware that Spring Framework 4.2 also provides a CorsFilter
that use the same CORS processing logic that @CrossOrigin
and addCorsMappings(CorsRegistry registry)
approaches. By passing an UrlBasedCorsConfigurationSource
实例用于 CorsFilter
构造函数参数,您可以轻松获得与 Spring 原生 CORS 全局支持一样强大的功能。
如果您正在使用 Spring 引导(它支持 Filter
beans),它可能是这样的:
@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;
}
}
自 the Ingalls train has been realised 起,Spring 数据中的 CORS 支持现已开启。有两种处理方式:
通过 @RepositoryRestResource
接口指定 origins
、methods
和 allowedHeaders
的 @CrossOrigin
注释。
@CrossOrigin(...)
@RepositoryRestResource
public interface PageRepository extends CrudRepository<Page, Long> { ... }
RepositoryRestConfiguration
在 @Configuration
class 中的全局配置。然后不需要用 @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: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'corsFilter' is expected to be of type 'org.springframework.web.filter.CorsFilter' but was actually of type 'org.springframework.boot.web.servlet.FilterRegistrationBean
所以这就是我为我们的 REST API 中的所有端点获取 "global" CORS 配置的方法,无论它们是使用 Spring Data Rest 还是 Spring MVC,所有端点都受 Spring 安全保护。
我无法在正确的位置将 CorsFilter
连接到请求管道中,因此我分别配置了 SDR 和 MVC,但是通过此为它们的 CorsRegistry
使用了相同的配置帮手:
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());
}
这里有一些关于这个主题的进一步参考,帮助我得出这个答案:
我正试图从 angular 访问 spring 休息服务。
Spring rest 项目部署在 tomcat 服务器中,angular 是默认的 angular 服务器。
当它从 angular 进入服务时,我遇到了这个问题。
我试着关注
https://juristr.com/blog/2016/11/configure-proxy-api-angular-cli/
但问题依然存在。
感谢我的前辈'Abbas bhai',他建议请在spring配置文件中添加一些配置来避免这个问题,所以我在spring配置中添加了这段代码。
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
@ComponentScan("org.liferayasif.backend")
public class RestConfig extends WebMvcConfigurerAdapter{
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
/*
* (non-Javadoc)
* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#addCorsMappings(org.springframework.web.servlet.config.annotation.CorsRegistry)
* To avoid 'Access-Control-Allow-Origin'
* Above error arising when I am hitting from angular to our rest service
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
此方法解决了我的 'Access-Control-Allow-Origin' 问题。
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
作为参考可以下载我的整个项目
我的githuburllink:
https://github.com/asifaftab87/SpringPersistenceHibernate
分支机构 - 安全
项目 - 模型
RepositoryRestConfigurerAdapter 已从 3.1 中弃用,因此如果您使用上面的 spring 引导和数据休息版本 3.1,您可以直接实现 RepositoryRestConfigurer:
@Configuration
public class ConfigRepositoryRest implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.getCorsRegistry()
.addMapping("/**")
.allowedOrigins("http://localhost:3000");
}
}
我正在开发一个 Spring 带有 Rest 界面和前端 dart 的启动应用程序。
XMLHttpRequest 确实执行了一个完全正确处理的 OPTIONS 请求。在此之后,发出最终的 GET ("/products") 请求并失败:
请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源“http://localhost:63343”。
经过一些调试,我发现了以下内容:
AbstractHandlerMapping.corsConfiguration 为除 RepositoryRestHandlerMapping 之外的所有 Sub类 填充。在 RepositoryRestHandlerMapping 中,在创建时不存在/设置 corsConfiguration,因此它不会被识别为 cors 路径/资源。
=> 没有 CORS header 附加
这可能是问题所在吗?我该如何设置它?
配置类:
@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> {
}
原始请求 headers:
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
原始响应 headers:
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 引导 1.3.0.M2 Spring4.2.0.RC2
我错过了什么?
确实,在 Spring Data REST 2.6 (Ingalls) 之前,只有 HandlerMapping
个由 Spring MVC WebMvcConfigurationSupport
创建的实例和用 @CrossOrigin
注释的控制器是 CORS意识到。
但是现在 DATAREST-573 has been fixed, RepositoryRestConfiguration
now exposes a getCorsRegistry()
for global setup and @CrossOrigin
annotations on repositories are also recognized so this is the recommended approach. See
对于必须坚持使用 Spring Data REST 2.5 (Hopper) 或以前版本的人,我认为最好的解决方案是使用基于过滤器的方法。您显然可以将 Tomcat、Jetty 或 this one, but be aware that Spring Framework 4.2 also provides a CorsFilter
that use the same CORS processing logic that @CrossOrigin
and addCorsMappings(CorsRegistry registry)
approaches. By passing an UrlBasedCorsConfigurationSource
实例用于 CorsFilter
构造函数参数,您可以轻松获得与 Spring 原生 CORS 全局支持一样强大的功能。
如果您正在使用 Spring 引导(它支持 Filter
beans),它可能是这样的:
@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;
}
}
自 the Ingalls train has been realised 起,Spring 数据中的 CORS 支持现已开启。有两种处理方式:
通过
@RepositoryRestResource
接口指定origins
、methods
和allowedHeaders
的@CrossOrigin
注释。@CrossOrigin(...) @RepositoryRestResource public interface PageRepository extends CrudRepository<Page, Long> { ... }
RepositoryRestConfiguration
在@Configuration
class 中的全局配置。然后不需要用@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: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'corsFilter' is expected to be of type 'org.springframework.web.filter.CorsFilter' but was actually of type 'org.springframework.boot.web.servlet.FilterRegistrationBean
所以这就是我为我们的 REST API 中的所有端点获取 "global" CORS 配置的方法,无论它们是使用 Spring Data Rest 还是 Spring MVC,所有端点都受 Spring 安全保护。
我无法在正确的位置将 CorsFilter
连接到请求管道中,因此我分别配置了 SDR 和 MVC,但是通过此为它们的 CorsRegistry
使用了相同的配置帮手:
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());
}
这里有一些关于这个主题的进一步参考,帮助我得出这个答案:
我正试图从 angular 访问 spring 休息服务。 Spring rest 项目部署在 tomcat 服务器中,angular 是默认的 angular 服务器。 当它从 angular 进入服务时,我遇到了这个问题。 我试着关注
https://juristr.com/blog/2016/11/configure-proxy-api-angular-cli/
但问题依然存在。 感谢我的前辈'Abbas bhai',他建议请在spring配置文件中添加一些配置来避免这个问题,所以我在spring配置中添加了这段代码。
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
@ComponentScan("org.liferayasif.backend")
public class RestConfig extends WebMvcConfigurerAdapter{
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
/*
* (non-Javadoc)
* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#addCorsMappings(org.springframework.web.servlet.config.annotation.CorsRegistry)
* To avoid 'Access-Control-Allow-Origin'
* Above error arising when I am hitting from angular to our rest service
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
此方法解决了我的 'Access-Control-Allow-Origin' 问题。
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
作为参考可以下载我的整个项目
我的githuburllink:
https://github.com/asifaftab87/SpringPersistenceHibernate
分支机构 - 安全
项目 - 模型
RepositoryRestConfigurerAdapter 已从 3.1 中弃用,因此如果您使用上面的 spring 引导和数据休息版本 3.1,您可以直接实现 RepositoryRestConfigurer:
@Configuration
public class ConfigRepositoryRest implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.getCorsRegistry()
.addMapping("/**")
.allowedOrigins("http://localhost:3000");
}
}