wake-up-neo.net

Spring Data Rest und Cors

Ich entwickle eine Spring Boot-Anwendung mit einer Rest-Schnittstelle und einer Dart-Front. 

Das XMLHttpRequest führt eine OPTIONS-Anforderung aus, die vollkommen korrekt verarbeitet wird. Danach wird die letzte GET-Anforderung ("/ products") ausgegeben und schlägt fehl:

Kein Header 'Access-Control-Allow-Origin' ist in der angeforderten Ressource vorhanden. Origin ' http: // localhost: 63343 ' hat daher keinen Zugriff.

Nach einigem Debuggen habe ich Folgendes gefunden: Die AbstractHandlerMapping.corsConfiguration wird für alle Unterklassen außer RepositoryRestHandlerMapping ausgefüllt. Im RepositoryRestHandlerMapping ist zum Zeitpunkt der Erstellung keine corsConfiguration vorhanden/festgelegt und wird daher nicht als cors path/resource erkannt.
=> Keine CORS-Header angehängt
Könnte das das Problem sein? Wie kann ich es einstellen? 

Konfigurationsklassen:

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

   ...
}

Ich habe sogar versucht, den Cors per Annotation zu setzen:

@CrossOrigin( methods = RequestMethod.GET, allowCredentials = "false")
public interface ProductRepository extends CrudRepository<Product, String> {


}

Rohanforderungsheader:

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-Antwortheader:

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

Verwendete Versionen: Spring Boot 1.3.0.M2 Spring 4.2.0.RC2

Was vermisse ich?

50
Thomas Letsch

Vor Spring Data REST 2.6 (Ingalls) waren nur HandlerMapping-Instanzen, die von Spring MVC WebMvcConfigurationSupport erstellt wurden, und Controller, die mit @CrossOrigin kommentiert wurden, CORS-fähig.

Da DATAREST-573 nun jedoch behoben wurde, macht RepositoryRestConfiguration jetzt eine getCorsRegistry() für die globale Installation verfügbar, und @CrossOrigin-Anmerkungen zu Repositorys werden ebenfalls erkannt. Dies ist der empfohlene Ansatz. Siehe https://stackoverflow.com/a/42403956/1092077 answer für konkrete Beispiele.

Für Leute, die sich an Spring Data REST 2.5 (Hopper) oder frühere Versionen halten müssen, denke ich, ist die beste Lösung die Verwendung eines auf Filtern basierenden Ansatzes. Sie können natürlich Tomcat, Jetty oder this verwenden. Beachten Sie jedoch, dass Spring Framework 4.2 auch eine CorsFilter enthält, die dieselbe CORS-Verarbeitungslogik verwendet, die @CrossOrigin und addCorsMappings(CorsRegistry registry) angefahren werden. Durch die Übergabe einer UrlBasedCorsConfigurationSource -Instanz an den Konstruktorparameter CorsFilter können Sie leicht eine so mächtige Unterstützung wie die von Spring native CORS-Unterstützung weltweit erhalten.

Wenn Sie Spring Boot (der Filter-Beans unterstützt) verwenden, könnte dies etwa wie folgt aussehen:

@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;
    }
}
89

Seit der Ingalls-Zug wurde realisiert , ist die Unterstützung von CORS in Spring Data jetzt aktiv. Es gibt zwei Möglichkeiten, mit denen umzugehen:

  1. Die @CrossOrigin-Anmerkung mit Angabe von origins, methods und allowedHeaders über eine @RepositoryRestResource-Schnittstelle.

    @CrossOrigin(...)
    @RepositoryRestResource
    public interface PageRepository extends CrudRepository<Page, Long> { ... }
    
  2. Eine globale Konfiguration mit der RepositoryRestConfiguration innerhalb einer @Configuration-Klasse. Das Markieren von Repositories mit dem @CrossOrigin ist dann nicht erforderlich.

    @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);
         }
    
    }
    
15
Andrew Tobilko

Aus irgendeinem Grund funktionierte der in der oben genannten akzeptierten Antwort vorgeschlagene Ansatz für mich nach dem Upgrade von Spring Boot 1.5.2 auf 1.5.6 nicht.

Wie auch in @ BigDongs Kommentar hervorgehoben wurde, war die Ausnahme, die ich bekam: 

BeanInstantiationException: Instanziieren von [javax.servlet.Filter] fehlgeschlagen: Die Factory-Methode 'springSecurityFilterChain' hat eine Ausnahme ausgelöst. Die verschachtelte Ausnahme ist org.springframework.beans.factory.BeanNotOfRequiredTypeException: Das Bean 'corsFilter' wird voraussichtlich vom Typ 'org.springframework.web.filter.CorsFilter' sein, war jedoch tatsächlich vom Typ 'org.springframework.boot.web' .servlet.FilterRegistrationBean

Deshalb habe ich mir eine "globale" CORS-Konfiguration für alle Endpunkte in unserer REST - API vorgenommen, unabhängig davon, ob sie mit Spring Data Rest oder Spring MVC implementiert werden und alle Endpunkte durch Spring Security geschützt werden.

Ich konnte keine CorsFilter an der richtigen Stelle in die Anforderungspipeline einhaken. Daher habe ich SDR und MVC separat konfiguriert, jedoch die gleiche Konfiguration für ihre CorsRegistry über diesen Helfer verwendet:

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));
}

Und dann für 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);
            }
        };
    }
}

Und dann für 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());
}

Hier einige weitere Hinweise zu diesem Thema, die mir bei dieser Antwort geholfen haben: 

7

Ich habe versucht, den Frühlingsruhe-Service von eckig zu treffen. Das auf Tomcat-Server implementierte Frühlings-Rest-Projekt ist ein eckiger Standard-Server. Ich sah dieses Problem, wenn es von eckig auf den Dienst schlägt Folgen 

https://juristr.com/blog/2016/11/configure-proxy-api-angular-cli/

aber das Problem ist immer noch da .. Dank meines älteren 'Abbas bhai' schlug er vor, einige Konfigurationsdaten in der Konfigurationsdatei für den Frühling hinzuzufügen, um dieses Problem zu vermeiden. Daher habe ich diesen Code in der Konfiguration für den Frühling hinzugefügt.

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("/**");
    }

}

Diese Methode löste meine "Access-Control-Allow-Origin" -Cors.

@Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }

Als Referenz kann mein gesamtes Projekt heruntergeladen werden 

Mein Github-Link:

https://github.com/asifaftab87/SpringPersistenceHibernate

Branche - Sicherheit 

Projekt - Modell 

0
asifaftab87