스프링 부트에서 CSRF 설정을 URL 기반으로 세밀하게 제어하는 방법은 주로 `HttpSecurity` 설정을 통해 이루어집니다. 특정 URL 패턴에 대해서만 CSRF 보호를 활성화하거나 비활성화할 수 있습니다. **핵심 아이디어:** `HttpSecurity`의 `csrf()` 메서드를 통해 CSRF 설정을 시작하고, `ignoringAntMatchers()`, `requireCsrfProtectionMatcher()` 등의 메서드를 사용하여 특정 URL 패턴을 설정합니다. **설정 방법:** `WebSecurityConfigurerAdapter`를 상속받는 설정 클래스 또는 `@Bean`으로 `SecurityFilterChain`을 정의하는 방식에서 `HttpSecurity`를 설정합니다. **1. 특정 URL 패턴에 대해 CSRF 보호 비활성화:** ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf .ignoringRequestMatchers( new AntPathRequestMatcher("/api/public/**"), // /api/public/으로 시작하는 모든 요청에 대해 CSRF 비활성화 new AntPathRequestMatcher("/h2-console/**") // H2 콘솔 접근 시 CSRF 비활성화 (개발 환경) // 추가적인 URL 패턴 설정 가능 ) ) .authorizeHttpRequests(auth -> auth .anyRequest().permitAll() // 예시: 모든 요청 허용 ); return http.build(); } } ``` * `.csrf(csrf -> ...)`: CSRF 설정을 시작합니다. * `.ignoringRequestMatchers(...)`: 주어진 `RequestMatcher`와 일치하는 요청에 대해서는 CSRF 보호를 비활성화합니다. * `new AntPathRequestMatcher("/api/public/**")`: Ant 스타일의 URL 패턴을 사용하여 `/api/public/`으로 시작하는 모든 경로를 매칭합니다. * `new AntPathRequestMatcher("/h2-console/**")`: H2 콘솔 경로는 일반적으로 개발 환경에서 사용되므로 CSRF 보호를 비활성화하는 경우가 많습니다. * 여러 개의 `ignoringRequestMatchers()`를 사용하여 다양한 URL 패턴을 설정할 수 있습니다. **2. 특정 HTTP 메서드에 대해서만 CSRF 보호 비활성화:** 특정 URL 패턴에 대해 특정 HTTP 메서드(예: GET 요청)에 대해서만 CSRF 보호를 비활성화하고, 데이터를 변경하는 요청(POST, PUT, DELETE)에는 CSRF 보호를 유지할 수 있습니다. ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import java.util.Arrays; import java.util.List; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { List withoutCsrf = Arrays.asList( new AntPathRequestMatcher("/api/public/**", "GET"), // /api/public/으로 시작하는 GET 요청에 대해 CSRF 비활성화 new AntPathRequestMatcher("/some/readonly/path", "GET") // 추가적인 GET 요청 패턴 설정 가능 ); http .csrf(csrf -> csrf .ignoringRequestMatchers(withoutCsrf.toArray(new RequestMatcher[0])) ) .authorizeHttpRequests(auth -> auth .anyRequest().permitAll() // 예시: 모든 요청 허용 ); return http.build(); } } ``` * `new AntPathRequestMatcher("/api/public/**", "GET")`: `/api/public/`으로 시작하고 HTTP 메서드가 `GET`인 요청만 매칭합니다. **3. 특정 URL 패턴에 대해서만 CSRF 보호 활성화 (기본 설정 외 추가):** 기본적으로 CSRF 보호는 활성화되어 있지만, 특정 URL 패턴에 대해서만 명시적으로 활성화하거나, `ignoringRequestMatchers()`로 제외했던 패턴 중 일부에 대해 다시 활성화할 수 있습니다. (일반적인 사용 사례는 아닐 수 있습니다.) ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import java.util.Arrays; import java.util.List; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { List requireCsrf = Arrays.asList( new AntPathRequestMatcher("/admin/**") // /admin/으로 시작하는 요청에 대해 CSRF 활성화 (명시적) // 추가적인 활성화 패턴 설정 가능 ); http .csrf(csrf -> csrf // .ignoringRequestMatchers(...) // 특정 패턴 비활성화 설정이 있을 경우 .requireCsrfProtectionMatcher(request -> { // 기본적으로 POST, PUT, DELETE 요청에 대해 CSRF 보호를 적용하고, // requireCsrf 리스트에 있는 패턴에 대해서도 적용 boolean defaultMatch = !request.getMethod().equalsIgnoreCase("GET"); return defaultMatch || requireCsrf.stream().anyMatch(matcher -> matcher.matches(request)); }) ) .authorizeHttpRequests(auth -> auth .anyRequest().permitAll() // 예시: 모든 요청 허용 ); return http.build(); } } ``` * `.requireCsrfProtectionMatcher(RequestMatcher)`: CSRF 보호를 적용할 요청을 결정하는 `RequestMatcher`를 설정합니다. * 위 예시에서는 기본적으로 GET 요청이 아닌 경우 CSRF 보호를 적용하고, 추가적으로 `/admin/**` 패턴과 일치하는 모든 요청에 대해 CSRF 보호를 적용합니다. **주의 사항:** * CSRF 보호를 특정 URL에 대해 비활성화하는 것은 보안 위험을 증가시킬 수 있습니다. 신중하게 결정해야 하며, 정말로 CSRF 보호가 불필요한 경우에만 적용해야 합니다. * RESTful API를 개발하는 경우, Stateless 특성을 유지하기 위해 CSRF 대신 다른 보안 메커니즘(예: JWT 기반 인증)을 사용하는 것을 고려할 수 있습니다. 이 경우 CSRF를 비활성화할 수 있습니다. * H2 콘솔과 같은 개발 도구에 대한 CSRF 비활성화는 개발 환경에서 편의를 위해 사용될 수 있지만, 프로덕션 환경에서는 보안을 위해 접근 제어를 설정하는 것이 좋습니다. **결론:** 스프링 부트에서 URL 기반으로 CSRF 설정을 제어하려면 `HttpSecurity` 설정을 활용하여 `ignoringRequestMatchers()` 또는 `requireCsrfProtectionMatcher()` 메서드를 사용하여 원하는 URL 패턴에 따라 CSRF 보호를 활성화하거나 비활성화할 수 있습니다. 보안상의 영향을 충분히 고려하여 설정을 적용해야 합니다.