Spring CORS No hay encabezado 'Access-Control-Allow-Origin' presente

85

Recibo el siguiente problema después de migrar web.xml a la configuración de Java

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

Basado en algunas referencias de Spring, se ha intentado el siguiente intento:

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

}

Los valores elegidos se tomaron de un filtro web.xml en funcionamiento:

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

¿Alguna idea de por qué el enfoque de configuración de Spring java no funciona como lo hizo el archivo web.xml?

Ian Mc
fuente

Respuestas:

112

Cambiar el CorsMapping de registry.addMapping("/*") a registry.addMapping("/**")in addCorsMappings.

Echa un vistazo a este CORS de primavera documentación de .

Desde el documentación -

Habilitar CORS para toda la aplicación es tan simple como:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

Puede cambiar fácilmente cualquier propiedad, así como también aplicar esta configuración CORS a un patrón de ruta específico:

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

Método de controlador Configuración CORS

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

Para habilitar CORS para todo el controlador:

@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) {
        // ...
    }
}

Incluso puede utilizar configuraciones CORS tanto a nivel de controlador como a nivel de método; Spring luego combinará los atributos de ambas anotaciones para crear una configuración CORS combinada.

@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
fuente
36
Habilitar CORS para toda la aplicación no me funciona.
Dimitri Kopriwa
4
El uso addCorsMappingno funcionó para mí, tentado a decir que es debido a la seguridad de primavera ..., sin embargo, agregar un corsConfigurationSourcebean como se sugiere aquí resolvió mi problema.
Geoffrey
1
Además, no debe olvidarse de permitir el registro de todos los clientes.addMapping ("/ **"). AllowedOrigins ("*"); spring.io/guides/gs/rest-service-cors
spacedev
1
eres realmente un salvavidas. Estoy usando Spring 4.2 y probé innumerables otras alternativas y todas simplemente no funcionan hasta que probé la forma de anulación de addCorsMappings. Puede o no ayuda se agrega el encabezado CORS estándar, así como Access-Control-Allow-Headers
Vyrnach
2
Su 2020, y la anotación de arranque de primavera todavía no funciona.
theprogrammer
14

Consejo útil: si está utilizando el descanso de datos de Spring, necesita un enfoque diferente.

@Component
public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter {

 @Override
 public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.getCorsRegistry().addMapping("/**")
            .allowedOrigins("http://localhost:9000");
  }
}
unión inversa
fuente
3
Gracias por esta publicación. Estaba perdiendo la esperanza cuando noté que su publicación decía que Spring Data REST usa un enfoque diferente. ¡Funciona totalmente para mí ahora!
Jonathan Crégut
2
RepositoryRestConfigurerAdapteres obsoleto. Simplemente implementa RepositoryRestConfigurerdirectamente.
Gustavo Rodrigues
9

Tuvimos el mismo problema y lo resolvimos usando la configuración XML de Spring como se muestra a continuación:

Agregue esto en su archivo xml de contexto

<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
fuente
4

Si está utilizando Spring Security ver> = 4.2, puede usar el soporte nativo de Spring Security en lugar de incluir el de Apache:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

El ejemplo anterior se copió de una publicación de blog de Spring en la que también puede encontrar información sobre cómo configurar CORS en un controlador, métodos de controlador específicos, etc. Además, también hay ejemplos de configuración XML, así como la integración de Spring Boot.

matsev
fuente
4

Siguiendo la respuesta de Omar, creé un nuevo archivo de clase en mi proyecto de API REST llamado WebConfig.javacon esta configuración:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

Esto permite que cualquier origen acceda a la API y la aplique a todos los controladores del proyecto Spring.

Shane
fuente
4

La respuesta de Omkar es bastante completa.

Pero una parte de la parte de configuración global ha cambiado.

Según la referencia de Spring Boot 2.0.2.RELEASE

A partir de la versión 4.2, Spring MVC es compatible con CORS. El uso de la configuración CORS del método de controlador con anotaciones @CrossOrigin en su aplicación Spring Boot no requiere ninguna configuración específica. La configuración de CORS global se puede definir registrando un bean WebMvcConfigurer con un método addCorsMappings (CorsRegistry) personalizado, como se muestra en el siguiente ejemplo:

@Configuration
public class MyConfiguration {

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

La mayoría responde en esta publicación usando WebMvcConfigurerAdapter , sin embargo

El tipo WebMvcConfigurerAdapter está en desuso

Desde Spring 5 solo necesita implementar la interfaz WebMvcConfigurer:

public class MvcConfig implements WebMvcConfigurer {

Esto se debe a que Java 8 introdujo métodos predeterminados en interfaces que cubren la funcionalidad de la clase WebMvcConfigurerAdapter

Shihe Zhang
fuente
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
fuente
0

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

Había configurado cors correctamente, pero lo que faltaba en webflux en RouterFuncion eran los encabezados de accept y contenttype APPLICATION_JSON como en este fragmento de código:

@Bean
RouterFunction<ServerResponse> routes() {
    return route(POST("/create")
                              .and(accept(APPLICATION_JSON))
                              .and(contentType(APPLICATION_JSON)), serverRequest -> create(serverRequest);
}
Rumido
fuente
0

Por alguna razón, si todavía alguien no puede omitir CORS, escriba el encabezado del navegador que desea acceder a su solicitud.

Agregue este bean dentro de su archivo de configuración.

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

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


        }
    };
}

De esta manera podemos decirle al navegador que estamos permitiendo el origen cruzado de todos los orígenes. si desea restringir desde una ruta específica, cambie el "*" a {' http: // localhost: 3000 ', ""}.

Útil referencia para comprender este comportamiento https://www.concretepage.com/spring-4/spring-4-rest-cors-integration-using-crossorigin-annotation-xml-filter-example

Anshul Kabra
fuente
0

Encontré la solución en Spring Boot usando la anotación @CrossOrigin .

@RestController
@CrossOrigin
public class WebConfig extends WebMvcConfigurerAdapter {

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