简体   繁体   English

Spring Data Rest 和 Cors

[英]Spring Data Rest and Cors

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. XMLHttpRequest 确实执行了一个完全正确处理的 OPTIONS 请求。 After this, the final GET ("/products") request is issued and fails:在此之后,发出最终的 GET ("/products") 请求并失败:

No 'Access-Control-Allow-Origin' header is present on the requested resource.请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin ' http://localhost:63343 ' is therefore not allowed access.因此,不允许访问 Origin ' http://localhost:63343 '。

After some debugging I have found the following: The AbstractHandlerMapping.corsConfiguration is populated for all Subclasses except RepositoryRestHandlerMapping.经过一些调试,我发现以下内容: AbstractHandlerMapping.corsConfiguration 为除 RepositoryRestHandlerMapping 之外的所有子类填充。 In the RepositoryRestHandlerMapping no corsConfiguration is present / set at creation time and so it won't get recognized as cors path / resource.在 RepositoryRestHandlerMapping 中,在创建时不存在/设置 corsConfiguration,因此它不会被识别为 cors 路径/资源。
=> No CORS headers attached => 没有附加 CORS 标头
Could that be the problem?这可能是问题吗? How can I set it?我该如何设置?

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?我想念什么?

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) 之前,只有 Spring MVC WebMvcConfigurationSupport创建的HandlerMapping实例和用@CrossOrigin注释的控制器是 CORS 感知的。

But now that 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.但是现在DATAREST-573已修复, RepositoryRestConfiguration现在公开getCorsRegistry()用于全局设置,并且存储库上的@CrossOrigin注释也被识别,因此这是推荐的方法。 See https://stackoverflow.com/a/42403956/1092077 answer for concrete examples.有关具体示例,请参阅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.对于必须坚持使用 Spring Data REST 2.5 (Hopper) 或以前版本的人,我认为最好的解决方案是使用基于过滤器的方法。 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.您显然可以使用 Tomcat、Jetty 或this one ,但请注意,Spring Framework 4.2 还提供了一个CorsFilter ,它使用与@CrossOriginaddCorsMappings(CorsRegistry registry)方法相同的 CORS 处理逻辑。 By passing an UrlBasedCorsConfigurationSource instance to the CorsFilter constructor parameter, you could easily get something as powerful as Spring native CORS global support.通过将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;
    }
}

Since the Ingalls train has been realised , the support of CORS in Spring Data is now on.自从实现了 Ingalls train 之后,Spring Data 中 CORS 的支持就开始了。 There are two ways to deal with:有两种处理方式:

  1. The @CrossOrigin annotation with specifying origins , methods , and allowedHeaders over a @RepositoryRestResource interface.所述@CrossOrigin注释与指定originsmethods ,和allowedHeaders通过@RepositoryRestResource接口。

     @CrossOrigin(...) @RepositoryRestResource public interface PageRepository extends CrudRepository<Page, Long> { ... }
  2. A global configuration with the RepositoryRestConfiguration inside a @Configuration class.@Configuration类中使用RepositoryRestConfiguration全局配置。 Marking repositories by the @CrossOrigin is not necessary then.然后不需要通过@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); } }

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; BeanInstantiationException:无法实例化 [javax.servlet.Filter]:工厂方法“springSecurityFilterChain”抛出异常; 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嵌套异常是 org.springframework.beans.factory.BeanNotOfRequiredTypeExcep .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挂钩到请求管道中,因此我分别配置了 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:这里有一些关于这个主题的进一步参考,帮助我想出了这个答案:

RepositoryRestConfigurerAdapter is 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");
}

} }

I was trying to hitting spring rest service from angular.我试图从 angular 达到弹簧休息服务。 Spring rest project deployed in tomcat server and angular is default angular server. Spring rest 项目部署在 tomcat 服务器中,angular 是默认的 angular 服务器。 I faced this issue when it is hitting from angular to service.当它从角度击中到服务时,我遇到了这个问题。 I tried to follow我试着跟随

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项目 - 模型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM