웹 프로젝트 (IBAS)/SpringBoot api 개편

[Spring Boot] 4. 로컬 개발을 위한 CORS 설정 - (2) Spring MVC 와 Spring Security

동현 유 2022. 4. 15. 00:08

CORS 정책을 모른다면 아래 글을 먼저 읽으시길 바랍니다.

 

[Spring Boot] 4. 로컬 개발을 위한 CORS 설정 - (1) w3c recommendation 파악

 

[Spring Boot] 4. 로컬 개발을 위한 CORS 설정 - (1) w3c recommendation 파악

https://fetch.spec.whatwg.org/ Fetch Standard fetch.spec.whatwg.org 프론트 단에서의 비동기 통신 요청 - XMLHttpRequest 객체를 이용한 AJAX(Asynchronous JavaScript And XML (en-US)) 프로그래밍을 용..

letsmakemyselfprogrammer.tistory.com


[2가지 설정 방법]

CORS 정책 설정은 Spring MVC 와 Spring Security 두 프레임워크에서 모두 설정이 가능하다. 

둘 중 하나만 설정해도 충분한데, 가장 중요한 점은 Spring Security 가 가장 앞단에서 사용자 요청을 처리하기 때문에, Spring Security 에서 cors 를 활성화 시키는 것을 꼭 기억하자!

 


1. Spring MVC

Spring MVC에서 CORS를 적용하는 방법은 크게 총 2가지로 나뉜다.

  1. 부분적으로 컨트롤러에서 CORS를 설정하는 방법 (Annotation based)
  2. 전역적으로 Spring MVC 설정에서 CORS를 설정하는 방법

 


(1) 컨트롤러에서 설정하는 방법

 

Handler 메소드에 @CrossOrigin 애노테이션을 붙이는 방법
@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) {
        // ...
    }
}
  • 모든 Origin이 허용되고
  • @RequestMapping 애노테이션에서 명시되어진 HTTP 메소드가(GET Method) 허용된다.
  • preflight 응답이 캐시되어지는 시간은 30분이다.

 

Controller에 @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 애노테이션을 추가 했고, 해당 컨트롤러에 속해있는 두 핸들러 메소드 모두에게 클래스 레벨에서 설정한 CORS정책이 적용된다.

@CrossOrigin 애노테이션을 통해 origins, methods, allowedHeaders, exposedHeaders, allowCredentials, maxAge 모두 설정할 수 있다.

 

클래스 레벨과 메소드 레벨 모두에게 @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) {
        // ...
    }
}

클래스 레벨의 @CrossOrigin 애노테이션이 기본으로 적용되고 핸들러 메소드의 @CrossOrigin 애노테이션이 추가로 적용된다.


 

(2) 전역적으로 설정하는 방법

부분적으로 컨트롤러 마다 설정하는 애노테이션 기반 설정의 대안으로 Spring은 컨트롤러 외부에서 전역으로 CORS 설정을 할 수 있게 해준다. 이는 필터 기반 솔루션을 사용하는 것과 유사하지만 Spring MVC 내에서 선언하고 @CrossOrigin 설정과 결합할 수 있다.

 

JavaConfig를 통해 CORS 전역 설정
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
                .allowedOrigins("http://www.example.com")
                .allowedMethods("*")
                .allowCredentials(false)
                .maxAge(3000);
    }
}

위의 JavaConfig를 통해 paths, origins, methods, allowedHeaders, exposedHeaders, allowCredentials, maxAge 모두 설정할 수 있다.

 

XML을 통해 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>

위의 XMLConfig를 통해 paths, origins, methods, allowedHeaders, exposedHeaders, allowCredentials, maxAge 모두 설정할 수 있다.

 


2. Spring Security

Spring Security에서 CORS를 다루는 가장 확실하고 쉬운 방법은 CorsFilter를 사용하는 것이다. 사용자는 다음과 같이 CorsConfigurationSource를 제공하여 CorsFilter를 Spring Security와 통합 할 수 있다.

Spring Security 사용시 CORS에 걸리지 않으려면 Authentication Filter 인증 보다 앞단계의 필터/인터셉터에서 path 검증로직이 일어나야만 한다.

 

The CORS configuration in Spring Security
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
            // by default uses a Bean by the name of corsConfigurationSource
			.cors().and()
			...
	
    // You can configure allowed Origin, Method, Header and Credential 
    // and how long, as a duration, the response from a pre-flight request can be eached by clients
	@Bean
	CorsConfigurationSource corsConfigurationSource() {
		CorsConfiguration configuration = new CorsConfiguration();
		configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
		configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        // you can configure many allowed CORS headers

		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}
}

 


3. Spring MVC 와 Security 을 둘 다 사용한다면

만약 Spring MVC의 CORS 지원을 사용한다면, Spring Security의 CorsConfigurationSource 설정을 생략(omit)할 수 있다. Spring Security는 Spring MVC에서 제공되어지는 CORS 설정을 자동으로 탐지하여 활용(leverage)할 것이다.