7.5 KiB
스프링 부트에서 CSRF 설정을 URL 기반으로 세밀하게 제어하는 방법은 주로 HttpSecurity 설정을 통해 이루어집니다. 특정 URL 패턴에 대해서만 CSRF 보호를 활성화하거나 비활성화할 수 있습니다.
핵심 아이디어:
HttpSecurity의 csrf() 메서드를 통해 CSRF 설정을 시작하고, ignoringAntMatchers(), requireCsrfProtectionMatcher() 등의 메서드를 사용하여 특정 URL 패턴을 설정합니다.
설정 방법:
WebSecurityConfigurerAdapter를 상속받는 설정 클래스 또는 @Bean으로 SecurityFilterChain을 정의하는 방식에서 HttpSecurity를 설정합니다.
1. 특정 URL 패턴에 대해 CSRF 보호 비활성화:
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 보호를 유지할 수 있습니다.
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<RequestMatcher> 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()로 제외했던 패턴 중 일부에 대해 다시 활성화할 수 있습니다. (일반적인 사용 사례는 아닐 수 있습니다.)
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<RequestMatcher> 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 보호를 활성화하거나 비활성화할 수 있습니다. 보안상의 영향을 충분히 고려하여 설정을 적용해야 합니다.