Spring MVC CORS not working for error controllers - spring

I have my Spring MVC application configured to use CORS as such:
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
This works fine for successful requests however when an exception is thrown and is picked up by my error handler, CORS headers are not added.
#ControllerAdvice
public class ApiErrorHandler {
#ExceptionHandler(value = HttpClientErrorException.class)
public ResponseEntity badRequest(Exception ex)
{
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ErrorBodyWrapper.wrapErrorInJson(ex.getMessage()));
}
}
Is there a reason CORS does not work for error handlers?
Thanks

I think by default the only method added to the mapping is GET,
In your "addCorsMappings" try to specify the methods you want to add the header to
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD");

Using Spring CorsFilter can resolve this problem.
#Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(0);
return bean;
}

Related

How to enable CORS in Spring

I tried doing this but it isn't working. I also tried adding #CrossOrigin on top of my controller class but that didn't work either.
#Configuration
public class CorsConfig {
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*"); //'*' allows all endpoints, Provide your URL/endpoint, if any.
config.addAllowedHeader("*");
config.addAllowedMethod("POST"); //add the methods you want to allow like 'GET', 'PUT',etc. using similar statements.
config.addAllowedMethod("GET");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
There are several ways to achieve that. You can do that on method level or global. For Example (source: https://www.baeldung.com/spring-cors):
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
#EnableWebMvc
public class CorsConfiguration implements WebMvcConfigurer
{
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("GET", "POST");
}
}
also take a look on the old thread: How to configure CORS in a Spring Boot + Spring Security application?
#Configuration
public class CorsConfig {
#Bean
public WebMvcConfigurer corsConfig() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")
.allowedOrigins("*")
.allowedHeaders("*")
.allowCredentials(false);
}
};
}
}
Try this once, it should work.

How Can I Disable ssl certificate Spring RestTemplate?

In my Spring boot project I am trying to intercept the following POST call "https: // localhost: 8080" but I get the following error:
java.lang.IllegalArgumentException: Invalid character found in method name
I already know that to solve the problem it would be enough to change from https to http. But I don't want this.
I want my code to be able to automatically handle this situation.
In any case if I try to reach
This is the configuration of my RestTemplate in the App class:
How could I go about solving the problem ??
This is the configuration of my RestTemplate in the App class:
#EnableFeignClients
#ServletComponentScan
#Import(EmbeddedTomcatConfiguration.class)
// uncomment to enable auditor
//#EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
#Bean
public RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
HttpClientBuilder.create().build());
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
return restTemplate;
}
#Autowired(required = true)
public void configureJackson(ObjectMapper jackson2ObjectMapper) {
// jackson2ObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
jackson2ObjectMapper.registerModule(new JavaTimeModule());
jackson2ObjectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
#Bean
public FilterRegistrationBean<CorsFilter> filterRegistrationBean() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = buildCorsConfiguration();
source.registerCorsConfiguration("/**", config);
final FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
private CorsConfiguration buildCorsConfiguration() {
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader(HttpHeaders.LOCATION);
return config;
}
}
How could I go about solving the problem ??

Spring Security CORS doesn't work for Http PUT method

I am getting 'Invalid CORS request' when I try to PutMapping of my API in Postman. But it is working fine for 'POST' and 'GET' mapping.
Why is it not working for the 'PUT' operation?
My Spring Boot version: 2.0
This is my config:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/h2-console/**/**").permitAll()
.antMatchers(HttpMethod.GET,"/user/get-request").permitAll()
.antMatchers(HttpMethod.POST,"/user/post-request").permitAll()
.antMatchers(HttpMethod.PUT,"/user/put-request").permitAll()
.and()
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtUserDetailService));
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").exposedHeaders("Authorization");
}
};
}
This is my controller :
#RestController
#RequestMapping("/user")
public class UserController {
#PutMapping("/put-request")
public void doResetPassword(#RequestBody String password) {
System.out.println("PUT MAPPING");
}
#PostMapping("/post-request")
public void doResetPassword(#RequestBody String password) {
System.out.println("POST MAPPING");
}
#GetMapping("/get-request")
public void doResetPassword() {
System.out.println("GET MAPPING");
}
}
It's much simpler than the accepted solution.
#Configuration
public class CrossOriginConfig {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedMethods("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS");
}
};
}
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(ImmutableList.of("*"));
configuration.setAllowedMethods(ImmutableList.of("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(ImmutableList.of("*"));
configuration.setExposedHeaders(ImmutableList.of("X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
I managed to allow cors request by adding this bean. You can configure setAllowedHeaders() and setExposedHeaders() by your need.
Also, I added this line to my controller;
#RequestMapping(value = "/auth")
#RestController
#CrossOrigin(origins = "*") //this line
public class AuthenticationController {..}
If your controller needs to handle on-the-fly OPTION request you can add this method to your controller. You can configure the value by your endpoint.
#RequestMapping(value = "/**/**",method = RequestMethod.OPTIONS)
public ResponseEntity handle() {
return new ResponseEntity(HttpStatus.OK);
}
If you are using a IIS server It was a problem with the WebDAVModule which seems to block PUT and DELETE methods by default!
<system.webServer>
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
</system.webServer>
I really hope no one else pain with that! =]
Fonte: https://mozartec.com/asp-net-core-error-405-methods-not-allowed-for-put-and-delete-requests-when-hosted-on-iis/
In Spring with Kotlin I did the following:
#Bean
fun corsConfigurationSource(): CorsConfigurationSource? {
val source = UrlBasedCorsConfigurationSource()
val corsConfig = CorsConfiguration()
.applyPermitDefaultValues()
.setAllowedOriginPatterns(listOf("*"))
corsConfig.addAllowedMethod(HttpMethod.PUT)
source.registerCorsConfiguration("/**", corsConfig)
return source
}
I just want to add 3 things.
The accepted answer and the one below it are wrong ways of doing CORS.
If you are trying to configure CORS, that means you are trying to make your API accessible only by a number of clients you know. The lines
configuration.setAllowedOrigins(ImmutableList.of("*")); // from the first answer
.addMapping("/**") // from the second answer
make the API accessible by any client. If that is what you want, you can just do the following with out a need to configure another bean
http.cors().disable()
The issue in the question may happen when you allow origins with http and do your request using https. So be aware that those 2 are different.
Below is a working configuration
// In the import section
import static org.springframework.security.config.Customizer.withDefaults;
// In the HttpSecurity configuration
http.cors(withDefaults())
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200", "https://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Content-Type", "X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
configuration.setExposedHeaders(Arrays.asList("Content-Type", "X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
I'm using Spring Security and Spring Boot 2.1.2. In my specific case, the PUT call worked after I explicitly declared the "PUT" method in the setAllowedMethods() from CorsConfigurationSource bean. The headers can be chosen depending on the application behavior.
#Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final String headers = "Authorization, Access-Control-Allow-Headers, "+
"Origin, Accept, X-Requested-With, Content-Type, " +
"Access-Control-Request-Method, Custom-Filter-Header";
CorsConfiguration config = new CorsConfiguration();
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE")); // Required for PUT method
config.addExposedHeader(headers);
config.setAllowCredentials(true);
config.applyPermitDefaultValues();
source.registerCorsConfiguration("/**", config);
return source;
}

Enabling CORS in Spring Secondary Servlet

I am registering a secondary servlet using Spring boot's ServletRegistrationBean
#Configuration
public class CxfServletRegister {
#Bean
public ServletRegistrationBean getODataServletRegistrationBean() {
ServletRegistrationBean odataServletRegistrationBean = new ServletRegistrationBean(new CXFNonSpringJaxrsServlet(), "/odata.svc/*");
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("javax.ws.rs.Application", "org.apache.olingo.odata2.core.rest.app.ODataApplication");
initParameters.put("org.apache.olingo.odata2.service.factory", "com.cce.utils.JPAServiceFactory");
odataServletRegistrationBean.setInitParameters(initParameters);
return odataServletRegistrationBean;
}
}
I am building an OData application using Apache Olingo. I want CORS to be enabled for my service.
How do I enable CORS for this servlet?
PS I have tried the WebConfigurer bean from the Spring: Getting Started guides
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/greeting-javaconfig").allowedOrigins("*");
}
};
}
This doesn't work, probably because this is configuring spring web's default dispatcher servlet and not the additional servlet configured using the ServletRegistrationBean
I found a likely way to do it here:
https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
#Configuration
public class MyConfiguration {
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}

Enabling Cross Origin Resource Sharing for Spring Data Rest

I'm developing Spring (non-Boot) application with Spring 4.2.1 version. I've enabled CORS for Spring MVC in web configuration file.
#Configuration
#EnableWebMvc
#ComponentScan({"com.hello.web", "com.hello.rest"})
#Import(RestMvcConfig.class)
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
And it was working correct. But now i started to use String Data Rest 2.4 and integrated it with Spring MVC. How to enable Cross Origin Resources Sharing for Spring Data Rest controllers? I've tried to fix it with filter bean Spring Data Rest and Cors
#Configuration
public class RestMvcConfig extends RepositoryRestMvcConfiguration {
#Override
public RepositoryRestConfiguration config() {
RepositoryRestConfiguration config = super.config();
config.setBasePath("/api");
config.setDefaultMediaType(new MediaType("application", "json", Charset.forName("utf-8")));
return config;
}
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // you USUALLY want this
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
But CORS is still not allowed.
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403.
How to enable CORS for Spring Data Rest?

Resources