복붙노트

[SPRING] Spring Framework를 사용하여 OPTIONS 요청에 CORS 사용

SPRING

Spring Framework를 사용하여 OPTIONS 요청에 CORS 사용

내 PUT Ajax 호출을 할 때마다 다음 오류가 반환됩니다.

조사 2 일 후에 코드에 다음 해결책을 시도했습니다.

이 클래스는 필요한 클래스를로드하고 응용 프로그램을 실행하는 기본 클래스입니다.

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

DispatcherServilet 초기화 프로그램에서 dispatchOptionsRequest를 활성화합니다.

public abstract class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setInitParameter("dispatchOptionsRequest", "true");
        super.customizeRegistration(registration);
    }
}

모든 OPTIONS 요청을 처리하기위한 컨트롤러 :

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

}

해결법

  1. ==============================

    1.마지막으로, DispatcheServlet 사용자 정의 이니셜 라이저는 실제로 내 문제를 해결하는 클래스입니다. 내가 구현했던 optionsController 때문에 OPTIONS 요청이 실패했습니다. 잘못되었습니다.

    마지막으로, DispatcheServlet 사용자 정의 이니셜 라이저는 실제로 내 문제를 해결하는 클래스입니다. 내가 구현했던 optionsController 때문에 OPTIONS 요청이 실패했습니다. 잘못되었습니다.

    그래서 optionsController를 제거하고 OPTIONS 요청에 대한 Rest Controller에 handle 메소드를 추가하여 문제가 해결되었습니다.

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

    2.최신 버전의 Spring (4.2)을 사용하면 @CrossOrigin의 이점을 누릴 수 있습니다. 실제로 <4.2v Spring을 사용한다면 서블릿 필터를 생성하고 아래와 같이 CORS 지원을위한 헤더를들을 수 있습니다 :

    최신 버전의 Spring (4.2)을 사용하면 @CrossOrigin의 이점을 누릴 수 있습니다. 실제로 <4.2v Spring을 사용한다면 서블릿 필터를 생성하고 아래와 같이 CORS 지원을위한 헤더를들을 수 있습니다 :

    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() {
        }
    
    }
    

    Spring 부팅시이 필터를 Spring 빈으로 등록하면 Spring이 필터를 등록 할 수있다.

    이것이 당신을 도울 수 있기를 바랍니다.

  3. from https://stackoverflow.com/questions/37733501/enable-cors-for-options-request-using-spring-framework by cc-by-sa and MIT license