1. 개요

최신 브라우저에서 CORS (Cross-Origin Resource Sharing) 는 REST API를 통해 데이터를 소비하는 HTML5 및 JS 클라이언트의 출현과 관련된 사양입니다.

대부분의 경우 JS를 제공하는 호스트 (예 : example.com )는 데이터를 제공하는 호스트 (예 : api.example.com ) 다릅니다 . 이 경우 CORS는 도메인 간 통신을 가능하게합니다.

Spring은 모든 Spring 또는 Spring Boot 웹 애플리케이션에서 쉽고 강력한 구성 방법을 제공하여 CORS에 대한 최고급 지원 을 제공합니다.

2. 컨트롤러 방식 CORS 구성

CORS를 활성화하는 것은 간단 합니다. @CrossOrigin 어노테이션을 추가하기 만하면 됩니다.

이를 여러 가지 방법으로 구현할 수 있습니다.

2.1. @CrossOrigin A의 @ RequestMapping- 어노테이션 처리기 방법

@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin
    @RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

위의 예에서는 retrieve () 메서드에 대해 CORS 만 활성화했습니다 . @CrossOrigin 어노테이션에 대한 구성을 설정하지 않았 으므로 기본값을 사용합니다.

  • 모든 출처가 허용됩니다.
  • 허용되는 HTTP 메서드는 @RequestMapping 어노테이션에 지정된 메서드입니다 (이 예에서는 GET).
  • 프리 플라이트 응답이 캐시되는 시간 ( maxAge) 은 30 분입니다.

2.2. 컨트롤러의 @CrossOrigin

@CrossOrigin(origins = "http://example.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

이번에 는 클래스 수준에서 @CrossOrigin추가 했습니다 . 결과적으로 retrieve ()remove () 메서드 모두 활성화됩니다. 어노테이션 속성 ( origins , methods , allowedHeaders , exposedHeaders , allowCredentials 또는 maxAge) 중 하나의 값을 지정하여 구성을 사용자 지정할 수 있습니다 .

2.3. 컨트롤러 및 처리기 메서드의 @CrossOrigin

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin("http://example.com")
    @RequestMapping(method = RequestMethod.GET, "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

Spring은 병합 된 CORS 구성을 만들기 위해 두 어노테이션의 속성을 결합합니다.

이 예제에서 두 메소드의 maxAge 는 3600 초이고 remove () 메소드 는 모든 출처를 허용하지만 retrieve () 메소드 http://example.com의 출처 만 허용 합니다.

3. 글로벌 CORS 구성

세분화 된 어노테이션 기반 구성의 대안으로 Spring을 사용하면 컨트롤러에서 전역 CORS 구성을 정의 할 수 있습니다. 이것은 필터 기반 솔루션 을 사용하는 것과 유사 하지만 Spring MVC 내에서 선언하고 세분화 된 @CrossOrigin 구성 과 결합 할 수 있습니다 .

기본적으로 모든 출처와 GET, HEAD 및 POST 메서드가 허용됩니다.

3.1. JavaConfig

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

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

위의 예는 모든 오리진에서 애플리케이션의 모든 엔드 포인트에 대한 CORS 요청을 활성화합니다.

이것을 좀 더 잠그고 싶다면 registry.addMapping 메서드는 추가 구성에 사용할 수 있는 CorsRegistration 객체를 반환 합니다. 허용 된 원본의 배열을 지정할 수 있는 allowedOrigins 메서드도 있습니다. 런타임에 외부 소스에서이 배열을로드해야하는 경우 유용 할 수 있습니다.

또한 응답 헤더 및 사용자 지정 옵션을 설정하는 데 사용할 수있는 allowedMethods , allowedHeaders , exposedHeaders , maxAgeallowCredentials도 있습니다.

3.2. XML 네임 스페이스

이 최소 XML 구성은 JavaConfig와 동일한 기본 속성을 사용하여 / ** 경로 패턴 에서 CORS를 활성화합니다 .

<mvc:cors>
    <mvc:mapping path="/**" />
</mvc:cors>

사용자 정의 속성을 사용하여 여러 CORS 매핑을 선언 할 수도 있습니다.

<mvc:cors>

    <mvc:mapping path="/api/**"
        allowed-origins="http://domain1.com, http://domain2.com"
        allowed-methods="GET, PUT"
        allowed-headers="header1, header2, header3"
        exposed-headers="header1, header2" allow-credentials="false"
        max-age="123" />

    <mvc:mapping path="/resources/**"
        allowed-origins="http://domain1.com" />

</mvc:cors>

4. 스프링 Security이 적용된 CORS

프로젝트에서 Spring Security를 ​​사용하는 경우 CORS와 잘 작동하도록 추가 단계를 수행해야합니다. CORS를 먼저 처리해야하기 때문입니다. 그렇지 않으면 Spring Security는 Spring MVC에 도달하기 전에 요청을 거부합니다.

운 좋게도 Spring Security는 즉시 사용 가능한 솔루션을 제공합니다.

@EnableWebSecurity
	public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	    @Override
	    protected void configure(HttpSecurity http) throws Exception {
	        http.cors().and()...
	    }
	}

이 기사에서는 더 자세히 설명합니다.

5. 작동 원리

CORS 요청은 등록 된 다양한 HandlerMappings에 자동으로 발송됩니다 . CORS 프리 플라이트 요청을 처리하고 CorsProcessor 구현 ( 기본적으로 DefaultCorsProcessor )을 사용하여 CORS 단순 및 실제 요청을 가로 채 관련 CORS 응답 헤더 (예 : Access-Control-Allow-Origin )를 추가합니다.

CorsConfiguration을 사용하면 CORS 요청을 처리하는 방법 (허용 된 출처, 헤더 및 메서드 등)을 지정할 수 있습니다. 다양한 방법으로 제공 할 수 있습니다.

  • AbstractHandlerMapping # setCorsConfiguration ()을 사용하면 / api / ** 와 같은 경로 패턴에 매핑 된여러 CorsConfiguration 을 사용하여 을 지정할 수 있습니다.
  • 서브 클래스는 AbstractHandlerMapping # getCorsConfiguration (Object, HttpServletRequest) 메서드 를 재정 의하여 자체 CorsConfiguration제공 할 수 있습니다.
  • 핸들러는 CorsConfigurationSource 인터페이스 ( 현재 ResourceHttpRequestHandler 가 수행하는 것처럼)를 구현하여 각 요청에 대해 CorsConfiguration 을 제공 할 수 있습니다.

6. 결론

이 기사에서는 Spring이 애플리케이션에서 CORS를 활성화하기위한 지원을 제공하는 방법을 보여주었습니다.

컨트롤러 구성부터 시작했습니다. 하나의 특정 메서드 또는 전체 컨트롤러에 CORS를 활성화 하려면 @CrossOrigin 어노테이션 만 추가하면 됩니다.

마지막으로, 컨트롤러 외부에서 CORS 구성을 제어하려는 경우 JavaConfig 또는 XML을 사용하여 구성 파일에서 원활하게 수행 할 수 있음을 확인했습니다.

예제의 전체 소스 코드는 GitHub에서 사용할 수 있습니다 .