Java Spring Data Rest 和 Cors
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31724994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Data Rest and Cors
提问by Thomas Letsch
I am developing a Spring Boot application with a Rest interface and a dart fronted.
我正在开发一个带有 Rest 接口和 dart 前端的 Spring Boot 应用程序。
The XMLHttpRequest does execute a OPTIONS request which is handled totally correct. After this, the final GET ("/products") request is issued and fails:
XMLHttpRequest 确实执行了一个完全正确处理的 OPTIONS 请求。在此之后,发出最终的 GET ("/products") 请求并失败:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63343' is therefore not allowed access.
请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问Origin ' http://localhost:63343'。
After some debugging I have found the following:
The AbstractHandlerMapping.corsConfiguration is populated for all Subclasses except RepositoryRestHandlerMapping. In the RepositoryRestHandlerMapping no corsConfiguration is present / set at creation time and so it won't get recognized as cors path / resource.
=> No CORS headers attached
Could that be the problem? How can I set it?
经过一些调试,我发现以下内容: AbstractHandlerMapping.corsConfiguration 为除 RepositoryRestHandlerMapping 之外的所有子类填充。在 RepositoryRestHandlerMapping 中,在创建时不存在/设置 corsConfiguration,因此它不会被识别为 cors 路径/资源。
=> 没有附加 CORS 标头
这可能是问题吗?我该如何设置?
Configuration classes:
配置类:
@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");
}
...
}
I even tried to set the Cors per annotation:
我什至尝试为每个注释设置 Cors:
@CrossOrigin( methods = RequestMethod.GET, allowCredentials = "false")
public interface ProductRepository extends CrudRepository<Product, String> {
}
Raw request 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
Raw response 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
Versions used: Spring Boot 1.3.0.M2 Spring 4.2.0.RC2
使用的版本:Spring Boot 1.3.0.M2 Spring 4.2.0.RC2
What do I miss?
我想念什么?
采纳答案by Sébastien Deleuze
Indeed, before Spring Data REST 2.6 (Ingalls) only HandlerMapping
instances created by Spring MVC WebMvcConfigurationSupport
and controllers annotated with @CrossOrigin
were CORS aware.
事实上,在 Spring Data REST 2.6 (Ingalls) 之前,只有HandlerMapping
Spring MVC 创建的实例WebMvcConfigurationSupport
和使用注释的控制器才能@CrossOrigin
识别 CORS。
But now that DATAREST-573has 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 https://stackoverflow.com/a/42403956/1092077answer for concrete examples.
但是现在DATAREST-573已修复,RepositoryRestConfiguration
现在公开了getCorsRegistry()
全局设置,并且@CrossOrigin
存储库上的注释也被识别,因此这是推荐的方法。有关具体示例,请参阅https://stackoverflow.com/a/42403956/1092077答案。
For people that have to stick to Spring Data REST 2.5 (Hopper) or previous versions, I think the best solution is to use a filter based approach. You could obviously use Tomcat, Jetty or 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
instance to the CorsFilter
constructor parameter, you could easily get something as powerful as Spring native CORS global support.
对于必须坚持使用 Spring Data REST 2.5 (Hopper) 或以前版本的人,我认为最好的解决方案是使用基于过滤器的方法。您显然可以使用 Tomcat、Jetty 或this one,但请注意 Spring Framework 4.2 还提供了一个CorsFilter
使用相同的 CORS 处理逻辑@CrossOrigin
和addCorsMappings(CorsRegistry registry)
方法。通过将UrlBasedCorsConfigurationSource
实例传递给CorsFilter
构造函数参数,您可以轻松获得与 Spring 原生 CORS 全局支持一样强大的功能。
If you are using Spring Boot (which supports Filter
beans), it could be something like:
如果您使用的是 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;
}
}
回答by Andrew Tobilko
Since the Ingalls train has been realised, the support of CORS in Spring Data is now on. There are two ways to deal with:
自从实现了 Ingalls train 之后,Spring Data 中 CORS 的支持就开始了。有两种处理方式:
The
@CrossOrigin
annotation with specifyingorigins
,methods
, andallowedHeaders
over a@RepositoryRestResource
interface.@CrossOrigin(...) @RepositoryRestResource public interface PageRepository extends CrudRepository<Page, Long> { ... }
A global configuration with the
RepositoryRestConfiguration
inside a@Configuration
class. Marking repositories by the@CrossOrigin
is not necessary then.@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); } }
在接口
@CrossOrigin
上指定origins
、methods
和的注释。allowedHeaders
@RepositoryRestResource
@CrossOrigin(...) @RepositoryRestResource public interface PageRepository extends CrudRepository<Page, Long> { ... }
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); } }
回答by Johannes Rudolph
For some reason the approach suggested in the accepted answer above didn't work for me after upgrading from Spring Boot 1.5.2 to 1.5.6.
出于某种原因,从 Spring Boot 1.5.2 升级到 1.5.6 后,上面接受的答案中建议的方法对我不起作用。
As also pointed out by @BigDong's comment, the exception I got was:
正如@BigDong 的评论所指出的,我得到的例外是:
BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeExcep??tion: 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
BeanInstantiationException:无法实例化 [javax.servlet.Filter]:工厂方法“springSecurityFilterChain”抛出异常;嵌套异常是 org.springframework.beans.factory.BeanNotOfRequiredTypeExcep??tion:名为 'corsFilter' 的 Bean 应该是 'org.springframework.web.filter.CorsFilter' 类型,但实际上是 'org.springframework.boot 类型。 web.servlet.FilterRegistrationBean
So here's what I came up with to get a "global" CORS configuration for all endpoint in our REST API, whether they're implemented using Spring Data Rest or Spring MVC, with all endpoints protected by Spring Security.
因此,这就是我为 REST API 中的所有端点获取“全局”CORS 配置的想法,无论它们是使用 Spring Data Rest 还是 Spring MVC 实现的,所有端点都受 Spring Security 保护。
I wasn't able to hook a CorsFilter
into the request pipeline at the right point, so instead I configured SDR and MVC separately, however using the same configuration for their CorsRegistry
via this helper:
我无法CorsFilter
在正确的点将a 连接到请求管道中,因此我分别配置了 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));
}
And then for MVC:
然后对于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);
}
};
}
}
And then for SDR:
然后对于 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());
}
Here's some further reference on the subject that helped me come up with this answer:
这里有一些关于这个主题的进一步参考,帮助我想出了这个答案:
回答by asifaftab87
I was trying to hitting spring rest service from angular. Spring rest project deployed in tomcat server and angular is default angular server. I faced this issue when it is hitting from angular to service. I tried to follow
我试图从 angular 达到弹簧休息服务。Spring rest 项目部署在 tomcat 服务器中,angular 是默认的 angular 服务器。当它从角度击中到服务时,我遇到了这个问题。我试着跟随
https://juristr.com/blog/2016/11/configure-proxy-api-angular-cli/
https://juristr.com/blog/2016/11/configure-proxy-api-angular-cli/
but problem still there. Thanks to my senior 'Abbas bhai', he suggested please add some configuration in spring configuration file to avoid this problem, so I added this code in spring configuration.
但问题仍然存在。感谢我的前辈'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("/**");
}
}
This method resolved my 'Access-Control-Allow-Origin' cors.
这种方法解决了我的“访问控制允许来源”问题。
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
For reference can download my whole project
作为参考可以下载我的整个项目
My github url link:
我的 github 网址链接:
https://github.com/asifaftab87/SpringPersistenceHibernate
https://github.com/asifaftab87/SpringPersistenceHibernate
Branch - security
分公司-安全
Project - Model
项目 - 模型
回答by Fazel Farnia
RepositoryRestConfigurerAdapteris deprecated from 3.1 so if you used spring boot and data-rest version 3.1 above you can directly implement RepositoryRestConfigurer:
RepositoryRestConfigurerAdapter从 3.1 开始被弃用,所以如果你使用 spring boot 和 data-rest 3.1 以上版本,你可以直接实现RepositoryRestConfigurer:
@Configuration
public class ConfigRepositoryRest implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.getCorsRegistry()
.addMapping("/**")
.allowedOrigins("http://localhost:3000");
}
}
}