[Spring] 9. Spring Security-1

Kim yoon beom·2025년 5월 14일
0

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
        http.csrf(csrf -> csrf.disable())

🤔REST API + JWT 환경에서 CSRF 보호를 비활성화하는 이유

▶️1. CSRF 공격의 기본 원리

  • 쿠키 기반 인증 시스템에서 발생하는 취약점
  • 공격자가 사용자의 세션 쿠키를 악용해 의도치 않은 요청 전송
  • 예시: <img src="http://은행/송금?to=해커&금액=100000"> (사용자가 로그인 상태에서 이 이미지를 보면 자동으로 송금)

▶️2. REST API + JWT의 특성

(1) 쿠키를 사용하지 않음

  • JWT는 주로 Authorization 헤더에 담겨 전송됨
  • 브라우저가 자동으로 헤더를 추가하지 않음 → 공격자가 예측 불가
  • 쿠키가 없으므로 CSRF 공격 매개체가 존재하지 않음

(2) Stateless 설계

  • 서버가 클라이언트 상태를 저장하지 않음
  • 모든 요청에 인증 정보(JWT)를 명시적으로 포함시켜야 함
  • 세션 ID 같은 자동 전송 매커니즘이 없음

(3) 클라이언트의 역할

  • 모바일 앱, SPA(React/Vue), 서버-서버 통신 등 비브라우저 클라이언트가 주 사용자
  • 토큰을 수동으로 헤더에 추가해야 하므로 공격자가 위조하기 어려움

▶️3. Spring Security 공식 문서 권장 사항

"When you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection."
https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html#csrf-when

  • 비브라우저 클라이언트 전용 서비스 → CSRF 보호 불필요
  • JWT + Authorization 헤더 조합은 대표적인 사례

설정 예시

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable()) // CSRF 보호 비활성화
            .sessionManagement(session -> 
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            .addFilterBefore(jwtAuthFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

🤔 csrf(AbstractHttpConfigurer::disable)와 csrf(csrf -> csrf.disable())의 차이

전자의 경우, AbstractHttpConfigurer의 disable 메서드를 메서드 참조 방식으로 전달하여 비활성화

후자의 경우, 람다식으로 csrf.disable()을 호출하여 비활성화

  • 결론적으로 csrf 보호를 비활성화하는 효과는 동일하다.

Spring Security 6.x 이상에서 후자(람다 기반)의 스타일로 변경되면서 권장되지는 않음.

"스프링 부트 3.x.x 버전부터는 csrf().disable()이 적용 시 경고 문장이 뜬다. 이는 다음과 같이 바꿔주면 된다.
http.csrf().disable() => http.csrf(AbstractHttpConfigurer::disable)"


▶️4. 비활성화를 하는 이유


@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .httpBasic(AbstractHttpConfigurer::disable) // 기본 인증 비활성화
                .formLogin(AbstractHttpConfigurer::disable) // 폼 로그인 비활성화
                .csrf(AbstractHttpConfigurer::disable) // CSRF 보호 비활성화
                .sessionManagement(session ->
                        session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )

이렇게 설정하는 이유는 주로 REST API 서버와 같이 "상태를 저장하지 않는(stateless)" 서비스에 적합한 보안 구성을 만들기 위해서다.

각 설정을 비활성화하는 이유

1. CSRF 보호 비활성화

  • CSRF(Cross Site Request Forgery) 보호는 브라우저 기반의 폼 인증에서 중요하다.
  • 하지만 REST API처럼 브라우저가 아닌 클라이언트(예: 모바일 앱, 프론트엔드 SPA, 외부 시스템)만 접근하는 서비스에서는 CSRF 공격 위험이 거의 없다.
  • Spring Security 공식 문서에서도 "non-browser clients만을 위한 서비스라면 CSRF를 disable 해도 된다"고 명시하고 있다.

2. 폼 로그인(formLogin) 비활성화

  • 폼 로그인은 HTML 폼을 통한 사용자 인증(아이디/비밀번호 입력 화면)을 제공한다.
  • REST API 서버는 보통 자체 로그인 화면을 제공하지 않고, 토큰 기반 인증(JWT 등)을 사용한다.
  • 따라서 폼 로그인 기능을 비활성화한다.

3. 기본 인증(httpBasic) 비활성화

  • HTTP Basic 인증은 브라우저 팝업을 통해 사용자 이름과 비밀번호를 입력받는 방식이다.
  • REST API에서는 보안상 더 안전한 인증 방식(JWT, OAuth 등)을 선호하므로, 기본 인증을 비활성화한다.

4. 세션 비활성화(Stateless)

  • SessionCreationPolicy.STATELESS 설정은 서버가 세션(쿠키 등)을 생성하거나 저장하지 않게 만든다.
  • REST API는 "Stateless"가 원칙이므로, 매 요청마다 인증 정보를 포함해야 하며, 서버는 인증 상태를 세션에 저장하지 않는다.
  • 이로 인해 쿠키가 사용되지 않고, 모든 요청이 독립적으로 처리된다.
  • 세션을 사용하지 않으면, 세션 탈취(Session Hijacking) 등 세션 관련 보안 문제도 줄어든다.

  1. Spring Security -2 에서 계속..
    (완성) https://velog.io/@kimybeom/Spring-9.-Spring-Security-2
profile
나는.원한다.개발자

0개의 댓글