일단 필요한 전체코드 - 아래는 설명입니다.
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
// 허용할 도메인 설정 (명시적으로 설정)
configuration.setAllowedOrigins(Arrays.asList("<http://localhost:3000>", "<http://localhost:8000>"));
// 허용할 HTTP 메서드
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
// 허용할 헤더
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
// 인증 정보 허용 (쿠키나 인증정보)
configuration.setAllowCredentials(true);
// 노출할 헤더
configuration.setExposedHeaders(Arrays.asList("Authorization", "Content-Type"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration); // 모든 경로에 적용
return source;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable) // CSRF 비활성화
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions.disable()) // X-Frame-Options 비활성화
)
.cors(cors -> cors.configurationSource(corsConfigurationSource())) // CORS 설정 적용
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll() // Preflight 요청 허용
.anyRequest().permitAll() // 모든 요청 허용
)
.addFilterBefore(corsLoggingFilter(), UsernamePasswordAuthenticationFilter.class); // 필터 체인에 추가
return http.build();
}
// CORS에 걸린 도메인을 로그로 남기는 필터
@Bean
public Filter corsLoggingFilter() {
return new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 필터 초기화
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// CORS 관련 요청인지 확인
if (CorsUtils.isCorsRequest(httpRequest)) {
String origin = httpRequest.getHeader("Origin");
logger.info("CORS 요청 - Origin: {}", origin);
}
// 필터 체인 진행
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 필터 종료 처리
}
};
}
저는 일반적으로 3개의 빈을 커스터 마이징해 사용하고 있습니다.
corsConfigurationSource
이 메서드는 Spring 애플리케이션에서 CORS(Cross-Origin Resource Sharing) 설정을 정의하기 위해 사용됩니다. Spring Security 또는 일반 Spring Web 애플리케이션에서 다른 도메인에서의 HTTP 요청을 제어하기 위한 설정입니다.
코드 세부 설명
1. 메서드 선언:
- @Bean: Spring 컨테이너에 이 메서드의 리턴 값을 Bean으로 등록합니다. 이를 통해 Spring Security 또는 WebMvc 설정에서 이 Bean을 참조하여 CORS 구성을 사용합니다.
- CorsConfigurationSource: Spring에서 CORS 설정을 적용하기 위해 사용하는 인터페이스입니다.
2. CorsConfiguration 객체 생성:
- CorsConfiguration: CORS 설정을 정의할 수 있는 객체입니다. 이 객체에서 허용할 도메인, HTTP 메서드, 헤더 등을 설정합니다.
3. 허용할 도메인 설정 (AllowedOrigins):
- 설명: 외부에서 이 애플리케이션에 접근할 수 있는 도메인을 명시합니다.
- http://localhost:3000: React와 같은 프론트엔드 개발 환경에서 주로 사용됩니다.
- http://localhost:8000: 또 다른 허용 도메인.
- CORS 규칙은 기본적으로 도메인 간 요청을 차단하므로, 명시적으로 허용할 도메인을 지정해야 합니다.
4. 허용할 HTTP 메서드 (AllowedMethods):
- 설명: 허용할 HTTP 요청 메서드를 설정합니다.
- GET, POST, PUT, DELETE: 주로 사용되는 메서드.
- OPTIONS: 브라우저가 CORS 요청 전에 보내는 사전 요청(Preflight Request) 메서드입니다.
5. 허용할 헤더 (AllowedHeaders):
- 설명: 클라이언트에서 요청 시 사용할 수 있는 HTTP 헤더를 지정합니다.
- Authorization: 인증 정보를 포함한 요청을 허용.
- Content-Type: 요청 본문의 데이터 형식을 지정하는 헤더를 허용.
6. 인증 정보 허용 (AllowCredentials):
- 설명: 클라이언트에서 보낸 쿠키, 세션, 인증 정보를 허용할지 여부를 설정합니다.
- true: 인증 정보가 포함된 요청을 허용합니다.
7. 노출할 헤더 (ExposedHeaders):
- 설명: 클라이언트가 응답에서 접근할 수 있는 헤더를 명시적으로 지정합니다.
- 예: 서버가 Authorization 헤더를 응답에 포함했다면, 이를 클라이언트에서 읽을 수 있게 설정.
8. URL 패턴에 CORS 설정 적용:
- UrlBasedCorsConfigurationSource: URL 패턴에 따라 CORS 설정을 적용하는 클래스입니다.
- registerCorsConfiguration: 특정 경로(/**)에 위에서 정의한 CORS 설정을 등록합니다.
- /**: 모든 URL 경로에 대해 설정 적용.
securityFilterChain
Spring Security에서 SecurityFilterChain을 정의하며, HTTP 요청에 대한 보안 규칙과 필터 체인을 설정합니다. 최신 Spring Security 방식으로 보안 구성을 설정하기 위해 사용됩니다.
세부 코드 설명:
1. 메서드 선언:
- @Bean: 이 메서드가 반환하는 SecurityFilterChain 객체를 Spring 컨테이너에서 관리합니다.
- SecurityFilterChain: HTTP 요청에 대한 보안 필터 체인을 구성하는 객체입니다.
- HttpSecurity: Spring Security의 보안 설정 API를 제공하는 핵심 클래스입니다.
2. CSRF 비활성화:
- 설명: CSRF(Cross-Site Request Forgery) 보호를 비활성화합니다.
- 일반적으로 REST API 서버에서는 CSRF 보호가 필요 없으므로 비활성화합니다.
3. X-Frame-Options 비활성화:
- 설명: 브라우저의 X-Frame-Options 헤더 설정을 비활성화합니다.
- 사용 목적: HTML <iframe> 요소를 사용할 때 차단되지 않도록 하기 위함.
- 예: H2 데이터베이스 콘솔처럼 iframe을 사용하는 UI를 지원하려는 경우.
4. CORS 설정 적용:
- 설명: 미리 정의된 CORS 정책(corsConfigurationSource() 메서드)을 적용합니다.
- CORS 설정은 다른 도메인에서 서버에 요청할 때의 규칙을 정의합니다.
5. Preflight 요청 허용:
- 설명: 브라우저가 Preflight 요청(HTTP OPTIONS)을 보내는 경우 인증 없이 허용합니다.
- Preflight 요청은 CORS 요청 전에 브라우저가 서버와 통신하기 위해 보내는 사전 요청입니다.
6. 모든 요청 허용:
- 설명: 모든 요청을 인증 없이 허용합니다.
- 개발 환경에서 보안을 최소화하거나, 외부 보안 장치로 보호되는 API의 경우 사용됩니다.
- 실제 프로덕션 환경에서는 더 구체적인 인증 및 권한 설정이 필요합니다.
7. Custom Filter 추가:
- 설명: 사용자 정의 필터(corsLoggingFilter())를 Spring Security의 기본 필터 체인에 추가합니다.
- UsernamePasswordAuthenticationFilter 앞에 위치합니다.
- 사용 목적: CORS 관련 요청을 로깅하거나 추가 처리를 하기 위한 필터를 삽입합니다.
corsLoggingFilter
Spring Filter를 정의하며, HTTP 요청 중 CORS 관련 요청을 로깅하기 위해 사용됩니다. 클라이언트에서 들어오는 CORS 요청의 Origin 헤더 값을 확인하고, 이를 로깅합니다.
주요 동작 설명:
1. 메서드 선언:
- @Bean: 이 메서드의 반환 객체를 Spring 컨테이너에서 관리하는 Bean으로 등록합니다.
- Filter: Java EE에서 제공하는 인터페이스로, HTTP 요청/응답 처리를 가로채거나 로직을 추가할 수 있습니다.
2. Filter 인터페이스 익명 구현체:
- 익명 클래스를 사용해 Filter 인터페이스를 구현합니다.
- init, doFilter, destroy 메서드를 오버라이드하여 필터 동작을 정의합니다.
3. init(FilterConfig filterConfig)
- 설명: 필터 초기화 시 호출됩니다.
- 사용 예: 필터가 동작하는 데 필요한 리소스나 설정을 초기화할 수 있습니다.
- 현재 구현에서는 특별한 초기화 작업을 수행하지 않습니다.
4. doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- doFilter의 역할:
- 요청/응답을 가로채 필요한 처리를 수행한 후, 체인의 다음 필터로 요청을 전달합니다.
- 이 메서드는 필터의 핵심 동작을 정의합니다.
- 동작 설명:
- 요청 객체를 HttpServletRequest로 캐스팅.
- CORS 요청인지 확인:
- CorsUtils.isCorsRequest(httpRequest)를 사용하여 요청이 CORS 관련 요청인지 검사합니다.
- Origin 헤더 로깅:
- 요청의 Origin 헤더 값을 로깅하여 CORS 요청의 출처를 기록합니다.
- 체인 진행:
- chain.doFilter(request, response)를 호출하여 요청을 필터 체인의 다음 단계로 전달합니다.
5. destroy()
- 설명: 필터가 종료될 때 호출됩니다.
- 사용 예: 필터 동작에 사용된 리소스를 정리하거나 종료 작업을 수행합니다.
- 현재 구현에서는 특별한 종료 작업을 수행하지 않습니다.
'Spring - Spring Boot' 카테고리의 다른 글
Spring - Spring Boot - Swagger 설정하기 (0) | 2024.12.12 |
---|---|
Spring Security - 1 - 설정 (2) | 2024.12.04 |