Spring CORS Nenhum cabeçalho 'Access-Control-Allow-Origin' está presente

89

Estou recebendo o seguinte problema após portar web.xml para a configuração java

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

Com base em algumas referências do Spring, a seguinte tentativa foi tentada:

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

}

Os valores escolhidos foram retirados de um filtro web.xml funcional:

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

Alguma ideia de por que a abordagem de configuração do Spring java não está funcionando como o arquivo web.xml funcionou?

Ian Mc
fonte

Respostas:

115

Altere o método CorsMapping de registry.addMapping("/*")para registry.addMapping("/**")no addCorsMappingsmétodo.

Confira esta documentação do Spring CORS .

Da documentação -

Ativar CORS para todo o aplicativo é tão simples quanto:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

Você pode alterar facilmente qualquer propriedade, bem como aplicar esta configuração CORS a um padrão de caminho 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);
    }
}

Configuração do método CORS do controlador

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

Para habilitar CORS para todo o 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) {
        // ...
    }
}

Você pode até usar configurações de CORS em nível de controlador e em nível de método; O Spring combinará os atributos de ambas as anotações para criar a configuração CORS mesclada.

@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
fonte
37
Ativar o CORS para todo o aplicativo não funciona para mim.
Dimitri Kopriwa,
4
Usar addCorsMappingnão funcionou para mim, tentado a dizer que é por causa da segurança da mola ..., porém adicionar um corsConfigurationSourcebean como sugerido aqui resolveu meu problema.
Geoffrey
1
Também não se deve esquecer de permitir todos os clientes registry.addMapping ("/ **"). AllowedOrigins ("*"); spring.io/guides/gs/rest-service-cors
spacedev
1
você é realmente um salva-vidas. Estou usando o Spring 4.2 e tentei inúmeras outras alternativas e todas elas simplesmente não funcionam até que tentei a forma de substituição addCorsMappings. Pode ou não ajudar, foi adicionado o cabeçalho CORS padrão, bem como Access-Control-Allow-Headers
Vyrnach
2
É 2020 e a anotação de boot de primavera ainda não funciona.
theprogrammer
15

Dica útil - se você estiver usando o descanso de dados do Spring, precisará de uma abordagem diferente.

@Component
public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter {

 @Override
 public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.getCorsRegistry().addMapping("/**")
            .allowedOrigins("http://localhost:9000");
  }
}
encadernação reversa
fonte
3
Obrigado por este post. Eu estava meio que perdendo as esperanças quando notei sua postagem dizendo que o Spring Data REST usa uma abordagem diferente. Funciona totalmente para mim agora!
Jonathan Crégut
2
RepositoryRestConfigurerAdapterestá obsoleto. Apenas implementa RepositoryRestConfigurerdiretamente.
Gustavo Rodrigues
11

Tivemos o mesmo problema e o resolvemos usando a configuração XML do Spring conforme abaixo:

Adicione isso ao seu arquivo 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
fonte
5

Se você estiver usando Spring Security ver> = 4.2, você pode usar o suporte nativo do Spring Security em vez de incluir o do Apache:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

O exemplo acima foi copiado de uma postagem do blog Spring na qual você também pode encontrar informações sobre como configurar o CORS em um controlador, métodos de controlador específicos, etc. Além disso, há também exemplos de configuração XML, bem como integração Spring Boot.

Matsev
fonte
5

Seguindo a resposta de Omar, criei um novo arquivo de classe em meu projeto de API REST chamado WebConfig.javacom esta configuração:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

Isso permite que qualquer origem acesse a API e a aplica a todos os controladores no projeto Spring.

Shane
fonte
5

A resposta de Omkar é bastante abrangente.

Mas alguma parte da configuração global mudou.

De acordo com a referência do spring boot 2.0.2.RELEASE

A partir da versão 4.2, Spring MVC suporta CORS. Usar o método do controlador de configuração CORS com anotações @CrossOrigin em seu aplicativo Spring Boot não requer nenhuma configuração específica. A configuração CORS global pode ser definida registrando um bean WebMvcConfigurer com um método addCorsMappings (CorsRegistry) customizado, conforme mostrado no exemplo a seguir:

@Configuration
public class MyConfiguration {

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

A maioria das respostas neste post usando WebMvcConfigurerAdapter, no entanto

O tipo WebMvcConfigurerAdapter está obsoleto

Desde o Spring 5 você só precisa implementar a interface WebMvcConfigurer:

public class MvcConfig implements WebMvcConfigurer {

Isso ocorre porque o Java 8 introduziu métodos padrão em interfaces que cobrem a funcionalidade da classe WebMvcConfigurerAdapter

Shihe Zhang
fonte
2

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

Eu também recebi mensagens como No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.

Eu havia configurado os cors corretamente, mas o que faltava no webflux em RouterFuncion era aceitar e contenttype os cabeçalhos APPLICATION_JSON como neste pedaço de código:

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

como @Geoffrey apontou, com o spring security, você precisa de uma abordagem diferente, conforme descrito aqui: Spring Boot Security CORS

mulher
fonte
0

Por algum motivo, se ainda assim alguém não conseguir ignorar o CORS, escreva o cabeçalho de qual navegador deseja acessar sua solicitação.

Adicione este bean dentro de seu arquivo de configuração.

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

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


        }
    };
}

Desta forma, podemos dizer ao navegador que estamos permitindo origem cruzada de todas as origens. se você deseja restringir de um caminho específico, altere o "*" para {' http: // localhost: 3000 ', ""}.

Referência útil para entender esse comportamento https://www.concretepage.com/spring-4/spring-4-rest-cors-integration-using-crossorigin-annotation-xml-filter-example

Anshul Kabra
fonte
0

Eu encontrei a solução na inicialização do Spring usando a anotação @CrossOrigin .

@RestController
@CrossOrigin
public class WebConfig extends WebMvcConfigurerAdapter {

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