300===Dev Framework/Spring Security

Spring Security - 웹 애플리케이션 보안의 든든한 수문장 🛡️

블로글러 2025. 5. 29. 09:10

여러분, 웹 애플리케이션을 만들 때 가장 걱정되는 게 뭔가요? 바로 보안이죠! 😰 "내 사이트가 해킹당하면 어떡하지?", "사용자 정보가 유출되면?" 이런 걱정, 다들 해보셨을 거예요. Spring Security는 이런 걱정을 덜어주는 Spring 생태계의 강력한 보안 프레임워크입니다!

등장 배경

과거 웹 애플리케이션들은 대부분 세션 기반 인증을 사용했어요. 사용자가 로그인하면 서버에서 세션을 생성하고, 클라이언트는 쿠키로 세션 ID를 받아서 매 요청마다 전송했죠. 하지만 이 방식에는 몇 가지 문제점이 있었어요:

  • 서버 부담: 많은 사용자의 세션 정보를 서버 메모리에 저장해야 함
  • 확장성 문제: 여러 서버를 사용할 때 세션 동기화가 필요함
  • 모바일/SPA 제약: RESTful API와 잘 맞지 않음

그래서 2003년 말, Ben Alex라는 개발자가 'Acegi Security'라는 이름으로 프로젝트를 시작했어요. 2008년 4월, 이 프로젝트는 Spring Security 2.0.0이라는 이름으로 Spring 포트폴리오에 공식적으로 포함되었죠! 🎉

Spring Security가 해결하는 문제들 🔧

  1. 인증(Authentication) 문제: "너 누구야?" 라는 질문에 답하는 것

    • 다양한 인증 방식 지원 (Form 로그인, JWT, OAuth2 등)
    • 비밀번호 암호화 및 관리
    • Remember-Me 기능
  2. 인가(Authorization) 문제: "너 이거 할 수 있어?" 라는 질문에 답하는 것

    • URL 기반 접근 제어
    • 메소드 수준의 보안 (@PreAuthorize, @PostAuthorize)
    • 역할 기반 접근 제어 (RBAC)
  3. 보안 위협 방어:

    • CSRF(Cross-Site Request Forgery) 공격 방어
    • Session Fixation 공격 방어
    • 클릭재킹(Clickjacking) 방어
    • XSS(Cross-Site Scripting) 방어

핵심 원리 🔍

Spring Security의 핵심은 필터 체인(Filter Chain) 이에요! 클라이언트의 요청이 컨트롤러에 도달하기 전에 여러 보안 필터를 거치게 됩니다.

┌─────────────┐     ┌──────────────────┐     ┌──────────────────┐
│   Client    │────▶│ DelegatingFilter │────▶│ FilterChainProxy │
└─────────────┘     │      Proxy       │     └──────────────────┘
                    └──────────────────┘              │
                                                      ▼
                                         ┌────────────────────────┐
                                         │  SecurityFilterChain   │
                                         └────────────────────────┘
                                                      │
        ┌─────────────────────────────────────────────┴──────────────┐
        │                                                            │
        ▼                                                            ▼
┌──────────────────┐  ┌────────────────────┐  ┌───────────────────┐
│ Authentication   │  │ Authorization      │  │ Exception         │
│ Filter           │  │ Filter             │  │ Translation Filter│
└──────────────────┘  └────────────────────┘  └───────────────────┘

주요 필터들과 역할 📋

필터 이름 역할 실행 순서
SecurityContextPersistenceFilter SecurityContext를 로드/저장 1번째
UsernamePasswordAuthenticationFilter Form 로그인 처리 중간
BasicAuthenticationFilter HTTP Basic 인증 처리 중간
JwtAuthenticationFilter JWT 토큰 검증 (커스텀) 중간
FilterSecurityInterceptor 최종 인가 결정 마지막

JWT 인증 플로우 예시 🔐

1. 로그인 요청
   Client ──────▶ /api/login (username, password)
                          │
2. 인증 처리            ▼
              AuthenticationManager
                          │
3. JWT 생성             ▼
              JwtTokenProvider.generateToken()
                          │
4. 토큰 반환            ▼
   Client ◀────── { "token": "eyJhbGc..." }

5. API 요청 (토큰 포함)
   Client ──────▶ /api/data 
                  Authorization: Bearer eyJhbGc...
                          │
6. 토큰 검증            ▼
              JwtAuthenticationFilter
                          │
7. 인가 확인            ▼
              FilterSecurityInterceptor

Spring Security 6.x 주요 변경사항 🆕

Spring Boot 3.0과 함께 Spring Security 6.0이 출시되면서 많은 변화가 있었어요:

// 이전 방식 (Deprecated)
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/api/public/**").permitAll()
        .anyRequest().authenticated();
}

// 새로운 방식 (Spring Security 6.x)
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/api/public/**").permitAll()
            .anyRequest().authenticated()
        )
        .build();
}

주의사항 및 팁 💡

⚠️ 이것만은 주의하세요!

  1. CSRF 토큰 설정

    • REST API에서는 보통 비활성화하지만, 웹 애플리케이션에서는 반드시 활성화
    • JWT를 사용할 때는 CSRF를 비활성화해도 안전
  2. 비밀번호 인코더

    • 절대 평문으로 저장하지 마세요!
    • BCryptPasswordEncoder 사용 권장
      @Bean
      public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
      }
  3. JWT 비밀키 관리

    • 하드코딩 금지! 환경변수나 설정 파일 사용
    • 충분히 긴 키 사용 (최소 256비트)

💡 꿀팁

  • Spring Security 디버깅 활성화: logging.level.org.springframework.security=DEBUG
  • 필터 체인 순서 확인: @EnableWebSecurity(debug = true) 사용
  • JWT 토큰 만료 시간은 적절히 설정 (보통 30분~1시간)

마치며

지금까지 Spring Security의 핵심 개념과 동작 원리에 대해 알아보았습니다. 처음에는 복잡해 보일 수 있지만, 필터 체인의 개념을 이해하면 Spring Security가 어떻게 우리 애플리케이션을 보호하는지 명확해집니다!

여러분의 웹 애플리케이션도 이제 든든한 수문장을 얻게 되었네요! 🛡️

궁금한 점이 있으시다면 댓글로 남겨주세요!

참고 자료 🔖


#SpringSecurity #JWT #Authentication #Authorization #SpringBoot

728x90
반응형