[스프링 Web Servlet 공식문서 읽기]1. Spring MVC (7) CORS

ybw·2021년 12월 30일

1.7 CORS

Spring MVC를 사용하면 CORS(Cross-Origin Resource Sharing)를 처리할 수 있습니다. 이 섹션에서는 그렇게 하는 방법에 대해 설명합니다.

1.7.1. Introduction

보안상의 이유로 브라우저는 현재 출처 외부의 리소스에 대한 AJAX 호출을 금지합니다. 예를 들어 한 탭에는 은행 계좌가 있고 다른 탭에는 evil.com이 있을 수 있습니다. evil.com의 스크립트는 귀하의 자격 증명으로 은행 API에 AJAX 요청을 할 수 없어야 합니다.

CORS(교차 출처 리소스 공유)는 IFRAME 또는 JSONP를 기반으로 하는 덜 안전하고 덜 강력한 해결 방법을 사용하는 대신 승인된 도메인 간 요청의 종류를 지정할 수 있도록 하는 대부분의 브라우저에서 구현되는 W3C 사양입니다.

1.7.2. Processing

CORS 사양은 실행 전, 단순 및 실제 요청을 구분합니다. CORS가 어떻게 작동하는지 알아보려면 이 기사를 읽거나 사양에서 자세한 내용을 참조하세요.

Spring MVC HandlerMapping 구현은 CORS에 대한 내장 지원을 제공합니다. 요청을 핸들러에 성공적으로 매핑한 후 HandlerMapping 구현은 지정된 요청 및 핸들러에 대한 CORS 구성을 확인하고 추가 조치를 취합니다. 실행 전 요청은 직접 처리되는 반면 단순하고 실제적인 CORS 요청은 가로채고 유효성이 검사되며 필수 CORS 응답 헤더가 설정됩니다.

교차 출처 요청(즉, Origin 헤더가 있고 요청 호스트와 다름)을 활성화하려면 명시적으로 선언된 일부 CORS 구성이 필요합니다. 일치하는 CORS 구성이 없으면 실행 전 요청이 거부됩니다. 단순하고 실제적인 CORS 요청의 응답에는 CORS 헤더가 추가되지 않으므로 브라우저는 이를 거부합니다.

HandlerMapping은 URL 패턴 기반 CorsConfiguration 매핑을 사용하여 개별적으로 구성할 수 있습니다. 대부분의 경우 응용 프로그램은 MVC Java 구성 또는 XML 네임스페이스를 사용하여 이러한 매핑을 선언하므로 단일 전역 맵이 모든 HandlerMapping 인스턴스에 전달됩니다.

HandlerMapping 수준의 전역 CORS 구성을 보다 세분화된 핸들러 수준 CORS 구성과 결합할 수 있습니다. 예를 들어 annotation이 달린 컨트롤러는 클래스 또는 메서드 수준 @CrossOrigin annotation을 사용할 수 있습니다(다른 핸들러는 CorsConfigurationSource를 구현할 수 있음).

전역 및 로컬 구성을 결합하기 위한 규칙은 일반적으로 추가적입니다(예: 모든 전역 및 모든 로컬 출처). 단일 값만 허용될 수 있는 속성의 경우, 예를 들어 allowCredentialsmaxAge, 로컬은 전역 값을 재정의합니다. 자세한 내용은 CorsConfiguration#combine(CorsConfiguration)을 참조하세요.

소스에서 자세히 알아보거나 고급 사용자 지정을 하려면 뒤에 있는 코드를 확인하세요.

  • CorsConfiguration
  • CorsProcessor, DefaultCorsProcessor
  • AbstractHandlerMapping

1.7.3 @CrossOrigin

@CrossOrigin annotation은 다음 예제와 같이 annotation이 달린 컨트롤러 메서드에 대한 교차 출처 요청을 활성화합니다.

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

    @CrossOrigin
    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @DeleteMapping("/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

기본적으로 @CrossOrigin은 다음을 허용합니다.

  • All origins.

  • All headers.

  • All HTTP methods to which the controller method is mapped.

allowCredentials는 기본적으로 활성화되어 있지 않습니다. 쿠키 및 CSRF 토큰과 같은 민감한 사용자별 정보를 노출하는 신뢰 수준을 설정하고 적절한 경우에만 사용해야 하기 때문입니다. 활성화되면 allowOrigins를 하나 이상의 특정 도메인으로 설정해야 합니다(특수 값 "*"는 아님). 또는 allowOriginPatterns 속성을 사용하여 동적 원본 집합과 일치시킬 수 있습니다.

maxAge는 30분으로 설정됩니다.

@CrossOrigin은 클래스 수준에서도 지원되며 다음 예제와 같이 모든 메서드에서 상속됩니다.

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

    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @DeleteMapping("/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

다음 예제와 같이 클래스 수준과 메서드 수준 모두에서 @CrossOrigin을 사용할 수 있습니다.

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

    @CrossOrigin("https://domain2.com")
    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @DeleteMapping("/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

1.7.4. Global Configuration

세분화된 컨트롤러 메서드 수준 구성 외에도 일부 전역 CORS 구성도 정의하고 싶을 것입니다. 모든 HandlerMapping에서 URL 기반 CorsConfiguration 매핑을 개별적으로 설정할 수 있습니다. 그러나 대부분의 애플리케이션은 이를 수행하기 위해 MVC Java 구성 또는 MVC XML 네임스페이스를 사용합니다.

기본적으로 전역 구성은 다음을 활성화합니다.

  • All origins.

  • All headers.

  • GET, HEADPOST 메서드.

allowCredentials는 기본적으로 활성화되어 있지 않습니다. 쿠키 및 CSRF 토큰과 같은 민감한 사용자별 정보를 노출하는 신뢰 수준을 설정하고 적절한 경우에만 사용해야 하기 때문입니다. 활성화되면 allowOrigins를 하나 이상의 특정 도메인으로 설정해야 합니다(특수 값 "*"는 아님). 또는 allowOriginPatterns 속성을 사용하여 동적 원본 집합과 일치시킬 수 있습니다.

maxAge는 30분으로 설정됩니다.

Java Configuration

MVC Java 구성에서 CORS를 활성화하려면 다음 예제와 같이 CorsRegistry 콜백을 사용할 수 있습니다.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/api/**")
            .allowedOrigins("https://domain2.com")
            .allowedMethods("PUT", "DELETE")
            .allowedHeaders("header1", "header2", "header3")
            .exposedHeaders("header1", "header2")
            .allowCredentials(true).maxAge(3600);

        // Add more mappings...
    }
}

XML Configuration

XML 네임스페이스에서 CORS를 활성화하려면 다음 예제와 같이 <mvc:cors> 요소를 사용할 수 있습니다.

<mvc:cors>

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

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

</mvc:cors>`

1.7.5. CORS Filter

내장 CorsFilter를 통해 CORS 지원을 적용할 수 있습니다.

Spring Security와 함께 CorsFilter를 사용하려는 경우 Spring Security에는 CORS에 대한 지원이 내장되어 있다는 점을 염두에 두십시오.

필터를 구성하려면 다음 예제와 같이 CorsConfigurationSource를 생성자에 전달합니다.

CorsConfiguration config = new CorsConfiguration();

// Possibly...
// config.applyPermitDefaultValues()

config.setAllowCredentials(true);
config.addAllowedOrigin("https://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);

CorsFilter filter = new CorsFilter(source);
profile
유병우

0개의 댓글