Spring CORS Brak nagłówka „Access-Control-Allow-Origin”

86

Po przeniesieniu pliku web.xml do konfiguracji java pojawia się następujący problem

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.

Bazując na kilku źródłach Spring, podjęto następującą próbę:

@Configuration
@ComponentScan(basePackageClasses = AppConfig.class, useDefaultFilters = false, includeFilters = {
        @Filter(org.springframework.stereotype.Controller.class) })
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/*").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "PUT")
                .allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",
                        "Access-Control-Request-Headers")
                .exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
                .allowCredentials(true).maxAge(3600);
    }

}

Wybrane wartości zostały pobrane z działającego filtru web.xml:

<filter>    
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
    <param-name>cors.allowed.origins</param-name>
    <param-value>*</param-value>
</init-param>
<init-param>
    <param-name>cors.allowed.methods</param-name>
    <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
    <param-name>cors.allowed.headers</param-name>
    <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
    <param-name>cors.exposed.headers</param-name>
    <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
    <param-name>cors.support.credentials</param-name>
    <param-value>true</param-value>
</init-param>
<init-param>
    <param-name>cors.preflight.maxage</param-name>
    <param-value>10</param-value>
</init-param> </filter> <filter-mapping>

<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Masz jakieś pomysły, dlaczego konfiguracja Spring java nie działa tak, jak plik web.xml?

Ian Mc
źródło

Odpowiedzi:

113

Zmień metodę CorsMapping z registry.addMapping("/*")na registry.addMapping("/**")in addCorsMappings.

Sprawdź tę dokumentację Spring CORS .

Z dokumentacji -

Włączenie CORS dla całej aplikacji jest tak proste, jak:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

Możesz łatwo zmienić dowolne właściwości, a także zastosować tę konfigurację CORS tylko do określonego wzorca ścieżki:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("http://domain2.com")
            .allowedMethods("PUT", "DELETE")
            .allowedHeaders("header1", "header2", "header3")
            .exposedHeaders("header1", "header2")
            .allowCredentials(false).maxAge(3600);
    }
}

Metoda kontrolera Konfiguracja CORS

@RestController
@RequestMapping("/account")
public class AccountController {
  @CrossOrigin
  @RequestMapping("/{id}")
  public Account retrieve(@PathVariable Long id) {
    // ...
  }
}

Aby włączyć CORS dla całego kontrolera -

@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @RequestMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

Można nawet użyć konfiguracji CORS na poziomie kontrolera i na poziomie metody; Spring następnie połączy atrybuty z obu adnotacji, aby utworzyć scaloną konfigurację CORS.

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin("http://domain2.com")
    @RequestMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}
Omkar Puttagunta
źródło
36
Włączenie CORS dla całej aplikacji nie działa dla mnie.
Dimitri Kopriwa
4
Używanie addCorsMappingnie zadziałało dla mnie, kusiło mnie, aby powiedzieć, że to z powodu wiosennego bezpieczeństwa ... jednak dodanie corsConfigurationSourcefasoli, jak sugerowano tutaj, rozwiązało mój problem.
Geoffrey
1
Nie należy również zapominać o zezwoleniu wszystkim klientom register.addMapping ("/ **"). AllowedOrigins ("*"); spring.io/guides/gs/rest-service-cors
spacedev
1
jesteś naprawdę ratownikiem. Używam Springa 4.2 i wypróbowałem niezliczone inne alternatywy i wszystkie one po prostu nie działają, dopóki nie wypróbuję metody nadpisywania addCorsMappings. Może pomóc, ale nie musi, dodać standardowy nagłówek CORS, a także Access-Control-Allow-Headers
Vyrnach
2
Jego 2020 i wiosenna adnotacja rozruchowa nadal nie działa.
theprogrammer
14

Pomocna wskazówka - jeśli korzystasz z Spring Data Rest, potrzebujesz innego podejścia.

@Component
public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter {

 @Override
 public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.getCorsRegistry().addMapping("/**")
            .allowedOrigins("http://localhost:9000");
  }
}
reverseebind
źródło
3
Dzięki za ten post. Trochę traciłem nadzieję, kiedy zauważyłem twój post mówiący, że Spring Data REST używa innego podejścia. Całkowicie działa teraz dla mnie!
Jonathan Crégut
2
RepositoryRestConfigurerAdapterjest przestarzałe. Po prostu wdraża RepositoryRestConfigurerbezpośrednio.
Gustavo Rodrigues
9

Mieliśmy ten sam problem i rozwiązaliśmy go za pomocą konfiguracji XML Springa, jak poniżej:

Dodaj to do swojego kontekstowego pliku xml

<mvc:cors>
    <mvc:mapping path="/**"
        allowed-origins="*"
        allowed-headers="Content-Type, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Authorization, X-Requested-With, requestId, Correlation-Id"
        allowed-methods="GET, PUT, POST, DELETE"/>
</mvc:cors>
Sabarish
źródło
4

Jeśli używasz Spring Security ver> = 4.2, możesz użyć natywnej obsługi Spring Security zamiast włączać Apache:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

Powyższy przykład został skopiowany z wpisu na blogu Springa, w którym można również znaleźć informacje o tym, jak skonfigurować CORS na kontrolerze, konkretne metody kontrolera itp. Ponadto są również przykłady konfiguracji XML, a także integracja Spring Boot.

matsev
źródło
4

Zgodnie z odpowiedzią Omara utworzyłem nowy plik klasy w moim projekcie REST API o nazwie WebConfig.javaz taką konfiguracją:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

Umożliwia to dowolnemu źródłu dostęp do interfejsu API i zastosowanie go do wszystkich kontrolerów w projekcie Spring.

Shane
źródło
4

Odpowiedź Omkara jest dość wyczerpująca.

Ale jakaś część globalnej konfiguracji uległa zmianie.

Zgodnie z odniesieniem do buta sprężynowego 2.0.2.RELEASE

Od wersji 4.2 Spring MVC obsługuje CORS. Korzystanie z metody kontrolera Konfiguracja CORS z adnotacjami @CrossOrigin w aplikacji Spring Boot nie wymaga żadnej konkretnej konfiguracji. Globalną konfigurację CORS można zdefiniować, rejestrując komponent bean WebMvcConfigurer za pomocą dostosowanej metody addCorsMappings (CorsRegistry), jak pokazano w poniższym przykładzie:

@Configuration
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**");
            }
        };
    }
}

Większość odpowiedzi w tym poście WebMvcConfigurerAdapterjednak używa

Typ WebMvcConfigurerAdapter jest przestarzały

Od wiosny 5 wystarczy zaimplementować interfejs WebMvcConfigurer:

public class MvcConfig implements WebMvcConfigurer {

Dzieje się tak, ponieważ Java 8 wprowadziła domyślne metody na interfejsach, które obejmują funkcjonalność klasy WebMvcConfigurerAdapter

Shihe Zhang
źródło
1

public class TrackingSystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(TrackingSystemApplication.class, args);
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("http://localhost:4200").allowedMethods("PUT", "DELETE",
                        "GET", "POST");
            }
        };
    }

}
Avinash Khadsan
źródło
0

Miałem też wiadomości typu No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.

Skonfigurowałem poprawnie cory, ale w webfluxie w RouterFuncion brakowało akceptacji i nagłówków contenttype APPLICATION_JSON jak w tym fragmencie kodu:

@Bean
RouterFunction<ServerResponse> routes() {
    return route(POST("/create")
                              .and(accept(APPLICATION_JSON))
                              .and(contentType(APPLICATION_JSON)), serverRequest -> create(serverRequest);
}
Rumid
źródło
0

Z jakiegoś powodu, jeśli nadal ktoś nie jest w stanie ominąć CORS, napisz nagłówek, którego przeglądarka chce uzyskać dostęp do twojego żądania.

Dodaj to ziarno do pliku konfiguracyjnego.

@Bean
public WebSecurityConfigurerAdapter webSecurity() {
    return new WebSecurityConfigurerAdapter() {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.headers().addHeaderWriter(
                    new StaticHeadersWriter("Access-Control-Allow-Origin", "*"));


        }
    };
}

W ten sposób możemy powiedzieć przeglądarce, że zezwalamy na cross-origin ze wszystkich źródeł. jeśli chcesz ograniczyć dostęp do określonej ścieżki, zmień „*” na {' http: // localhost: 3000 ', „”}.

Pomocne odniesienie do zrozumienia tego zachowania https://www.concretepage.com/spring-4/spring-4-rest-cors-integration-using-crossorigin-annotation-xml-filter-example

Anshul Kabra
źródło
0

Znalazłem rozwiązanie w wiosennym rozruchu, używając adnotacji @CrossOrigin .

@RestController
@CrossOrigin
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}
NafazBenzema
źródło