Spring MVC를 사용하면 CORS(Cross-Origin Resource Sharing)를 처리할 수 있습니다. 이 섹션에서는 이를 수행하는 방법을 설명합니다.
보안상의 이유로 브라우저는 현재 출처 외부의 리소스에 대한 AJAX 호출을 금지합니다. 예를 들어, 한 탭에는 은행 계좌를 두고 다른 탭에는 evil.com을 둘 수 있습니다. evil.com의 스크립트는 귀하의 자격 증명을 사용하여 은행 API에 AJAX 요청을 할 수 없어야 합니다. 예를 들어 귀하의 계좌에서 돈을 인출하는 경우입니다!
CORS(Cross-Origin Resource Sharing)는 IFRAME 또는 JSONP를 기반으로 하는 덜 안전하고 덜 강력한 해결 방법을 사용하는 대신 어떤 종류의 도메인 간 요청이 승인되는지 지정할 수 있도록 대부분의 브라우저에서 구현되는 W3C 사양입니다.
자격 증명 요청과 함께 CORS를 사용하려면 allowedCredentials
를 활성화해야 합니다. 이 옵션은 구성된 도메인에 대해 높은 수준의 신뢰를 설정하고 쿠키 및 CSRF 토큰과 같은 민감한 사용자별 정보를 노출하여 웹 애플리케이션의 공격 표면을 증가시킵니다.
자격 증명을 활성화하면 구성된 "*"
CORS 와일드카드가 처리되는 방식에도 영향을 줍니다.
allowOrigins
에서는 와일드카드가 승인되지 않지만, 대신에 allowOriginPatterns
속성을 사용하여 동적 원본 집합과 일치시킬 수 있습니다.
allowedHeaders
또는 allowedMethods
에 설정된 경우 Access-Control-Allow-Headers
및 Access-Control-Allow-Methods
응답 헤더는 CORS 실행 전 요청에 지정된 관련 헤더 및 메서드를 복사하여 처리됩니다.
exposedHeaders
에 설정된 경우 Access-Control-Expose-Headers
응답 헤더는 구성된 헤더 목록이나 와일드카드 문자로 설정됩니다. Access-Control-Allow-Credentials
가 true
로 설정된 경우 CORS 사양에서는 와일드카드 문자를 허용하지 않지만 대부분의 브라우저는 이를 지원하며 CORS 처리 중에 응답 헤더를 모두 사용할 수 있는 것은 아니므로 결과적으로 와일드카드 문자가 헤더가 됩니다. allowCredentials
속성 값에 관계없이 지정된 경우 사용되는 값입니다.
[Warning]
이러한 와일드카드 구성은 편리할 수 있지만 가능하면 더 높은 수준의 보안을 제공하기 위해 유한한 값 집합을 구성하는 것이 좋습니다.
CORS 사양은 실행 전 요청, 단순 요청, 실제 요청을 구분합니다. CORS의 작동 방식을 알아보려면 이 기사 등을 읽어보거나 사양에서 자세한 내용을 확인하세요.
Spring MVC HandlerMapping
구현은 CORS에 대한 기본 지원을 제공합니다. 요청을 핸들러에 성공적으로 매핑한 후 HandlerMapping
구현은 지정된 요청 및 핸들러에 대한 CORS 구성을 확인하고 추가 조치를 취합니다. 실행 전 요청은 직접 처리되는 반면 단순하고 실제 CORS 요청은 가로채서 검증되고 필수 CORS 응답 헤더가 설정됩니다.
원본 간 요청을 활성화하려면(즉, Origin
헤더가 존재하고 요청 호스트와 다름) 명시적으로 선언된 CORS 구성이 있어야 합니다. 일치하는 CORS 구성이 없으면 실행 전 요청이 거부됩니다. 단순 CORS 요청과 실제 CORS 요청의 응답에는 CORS 헤더가 추가되지 않으므로 브라우저는 이를 거부합니다.
각 HandlerMapping
은 URL 패턴 기반 CorsConfiguration
매핑을 사용하여 개별적으로 구성할 수 있습니다. 대부분의 경우 애플리케이션은 MVC Java 구성 또는 XML 네임스페이스를 사용하여 이러한 매핑을 선언하며, 이로 인해 단일 전역 맵이 모든 HandlerMapping
인스턴스에 전달됩니다.
HandlerMapping
수준의 전역 CORS 구성을 보다 세분화된 handler 수준 CORS 구성과 결합할 수 있습니다. 예를 들어 주석이 달린 컨트롤러는 클래스 또는 메서드 수준 @CrossOrigin
주석을 사용할 수 있습니다(다른 핸들러는 CorsConfigurationSource
를 구현할 수 있음).
글로벌 구성과 로컬 구성을 결합하는 규칙은 일반적으로 추가적입니다. 예를 들어 모든 글로벌 원본과 모든 로컬 원본이 있습니다. 단일 값만 허용되는 속성의 경우. allowCredentials
및 maxAge
, 로컬이 전역 값을 재정의합니다. 자세한 내용은 CorsConfiguration#combine(CorsConfiguration)
을 참조하세요.
[Tip]
소스에서 자세히 알아보거나 고급 사용자 정의를 수행하려면 뒤에 있는 코드를 확인하세요.
CorsConfiguration
CorsProcessor
,DefaultCorsProcessor
AbstractHandlerMapping
@CrossOrigin
@CrossOrigin
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
은 다음을 허용합니다.
모든 origins.
모든 헤더.
컨트롤러 메서드가 매핑되는 모든 HTTP 메서드입니다.
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) {
// ...
}
}
세분화된 컨트롤러 메서드 수준 구성 외에도 일부 전역 CORS 구성도 정의하고 싶을 수도 있습니다. 모든 HandlerMapping
에서 URL 기반 CorsConfiguration
매핑을 개별적으로 설정할 수 있습니다. 그러나 대부분의 애플리케이션은 이를 수행하기 위해 MVC Java 구성 또는 MVC XML 네임스페이스를 사용합니다.
기본적으로 전역 구성은 다음을 활성화합니다.
모든 기원.
모든 헤더.
GET
, HEAD
및 POST
메소드.
allowCredentials
는 기본적으로 활성화되어 있지 않습니다. 이는 민감한 사용자별 정보(예: 쿠키 및 CSRF 토큰)를 노출하는 신뢰 수준을 설정하고 적절한 경우에만 사용해야 하기 때문입니다. 활성화되면 AllowOrigins를 하나 이상의 특정 도메인(특수 값 "*"
은 아님)으로 설정해야 하거나, 대신에 allowOriginPatterns
속성을 사용하여 동적 원본 집합과 일치시킬 수 있습니다.
maxAge
는 30분으로 설정됩니다.
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 네임스페이스에서 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>
내장된 CorsFilter
를 통해 CORS 지원을 적용할 수 있습니다.
[Note]
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);