Enable CORS request for OPTIONS request using Spring Framework

Each time I call the Ajax PUT call to my service, it returns the following error:

XMLHttpRequest cannot load http: // localhost: 8080 / users / edit . The response to the request before the flight does not pass the access control check. There is no "Access-Control-Allow-Origin" header on the requested resource. Origin ' http: // localhost: 63342 ', therefore not allowed. The response had an HTTP status code of 403.

After 2 days of investigation, I tried to execute the following decision on my code.

This is the main class where I load the necessary classes and run the application:

@SpringBootApplication @EnableAutoConfiguration public class Application extends SpringBootServletInitializer{ public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(DispatcherServletInitializer.class, OptionsController.class,Application.class); } } 

The DispatcherServilet initializer, where I enable dispatchOptionsRequest:

 public abstract class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected void customizeRegistration(ServletRegistration.Dynamic registration) { registration.setInitParameter("dispatchOptionsRequest", "true"); super.customizeRegistration(registration); } } 

A controller to handle the entire OPTIONS request:

 @Controller public class OptionsController { @RequestMapping(method = RequestMethod.OPTIONS) public HttpServletResponse handle(HttpServletResponse theHttpServletResponse) throws IOException { theHttpServletResponse.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with"); theHttpServletResponse.addHeader("Access-Control-Max-Age", "60"); theHttpServletResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); theHttpServletResponse.addHeader("Access-Control-Allow-Origin", "*"); return theHttpServletResponse; } } 

What am I doing wrong with the configuration?

+14
java spring ajax spring-mvc cors
source share
2 answers

Finally, the DispatcheServlet configuration initializer was the class that really solved my problem. The OPTIONS request did not succeed because the Controller parameter was implemented, which was implemented, but this was incorrect.

So, I removed this parameter from the Controller and just adding the handle method to my break controller for the OPTIONS request, the problem was solved:

 @CrossOrigin(origins = "*", maxAge = 3600) @RestController @RequestMapping("/users") public class Users { @RequestMapping( value = "/edit", method = RequestMethod.PUT) public ResponseEntity<?> create(@RequestBody User user){ .... .... } @RequestMapping( value = "/**", method = RequestMethod.OPTIONS ) public ResponseEntity handle() { return new ResponseEntity(HttpStatus.OK); } } 
+18
source share

If you are using the modern version of Spring (4.2), you can use @CrossOrigin. Indeed, if you use Spring <4.2v, you can create a Servlet Filter and place the heard header to support CORS, as shown below:

 package it.valeriovaudi.web.filter; import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** Copyright 2015 Valerio Vaudi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ public class CORSFilter implements Filter { public static final String ACCESS_CONTROL_ALLOW_ORIGIN_NAME = "Access-Control-Allow-Origin"; public static final String DEFAULT_ACCESS_CONTROL_ALLOW_ORIGIN_VALUE = "*"; public static final String ACCESS_CONTROL_ALLOW_METHDOS_NAME = "Access-Control-Allow-Methods"; public static final String DEFAULT_ACCESS_CONTROL_ALLOW_METHDOS_VALUE = "POST, GET, OPTIONS, DELETE"; public static final String ACCESS_CONTROL_MAX_AGE_NAME = "Access-Control-Max-Age"; public static final String DEFAULT_ACCESS_CONTROL_MAX_AGE_VALUE = "3600"; public static final String ACCESS_CONTROL_ALLOW_HEADERS_NAME = "Access-Control-Allow-Headers"; public static final String DEFAULT_ACCESS_CONTROL_ALLOW_HEADERS_VALUE = "x-requested-with"; private String accessControlAllowOrigin = DEFAULT_ACCESS_CONTROL_ALLOW_ORIGIN_VALUE; private String accessControlAllowMethods = DEFAULT_ACCESS_CONTROL_ALLOW_METHDOS_VALUE; private String accessControlAllowMaxAge = DEFAULT_ACCESS_CONTROL_MAX_AGE_VALUE; private String accessControlAllowHeaders = DEFAULT_ACCESS_CONTROL_ALLOW_HEADERS_VALUE; /** * @return the method return a map that associated the name of paramiters in the web.xml to the class variable name for the header binding*/ private Map<String,String> initConfig(){ Map<String, String> result = new HashMap<>(); result.put(ACCESS_CONTROL_ALLOW_ORIGIN_NAME,"accessControlAllowOrigin"); result.put(ACCESS_CONTROL_ALLOW_METHDOS_NAME,"accessControlAllowMethods"); result.put(ACCESS_CONTROL_MAX_AGE_NAME,"accessControlAllowMaxAge"); result.put(ACCESS_CONTROL_ALLOW_HEADERS_NAME,"accessControlAllowHeaders"); return result; } @Override public void init(FilterConfig filterConfig) throws ServletException { String initParameterValue; Map<String, String> stringStringMap = initConfig(); for (Map.Entry<String, String> stringStringEntry : stringStringMap.entrySet()) { initParameterValue = filterConfig.getInitParameter(stringStringEntry.getKey()); // if the init paramiter value isn't null then set the value in the correct http header if(initParameterValue!=null){ try { getClass().getDeclaredField(stringStringEntry.getValue()).set(this, initParameterValue); } catch (IllegalAccessException | NoSuchFieldException ignored) { } } } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) servletResponse; response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_NAME, accessControlAllowOrigin); response.setHeader(ACCESS_CONTROL_ALLOW_METHDOS_NAME, accessControlAllowMethods); response.setHeader(ACCESS_CONTROL_MAX_AGE_NAME, accessControlAllowMaxAge); response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_NAME, accessControlAllowHeaders); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } } 

in Spring boot you can register this filter as Spring bean, and Spring will register the filter for you.

I hope this can help you.

+4
source share

All Articles