Spring Security - 웹 애플리케이션 보안의 든든한 수문장 🛡️
여러분, 웹 애플리케이션을 만들 때 가장 걱정되는 게 뭔가요? 바로 보안이죠! 😰 "내 사이트가 해킹당하면 어떡하지?", "사용자 정보가 유출되면?" 이런 걱정, 다들 해보셨을 거예요. Spring Security는 이런 걱정을 덜어주는 Spring 생태계의 강력한 보안 프레임워크입니다!
등장 배경
과거 웹 애플리케이션들은 대부분 세션 기반 인증을 사용했어요. 사용자가 로그인하면 서버에서 세션을 생성하고, 클라이언트는 쿠키로 세션 ID를 받아서 매 요청마다 전송했죠. 하지만 이 방식에는 몇 가지 문제점이 있었어요:
- 서버 부담: 많은 사용자의 세션 정보를 서버 메모리에 저장해야 함
- 확장성 문제: 여러 서버를 사용할 때 세션 동기화가 필요함
- 모바일/SPA 제약: RESTful API와 잘 맞지 않음
그래서 2003년 말, Ben Alex라는 개발자가 'Acegi Security'라는 이름으로 프로젝트를 시작했어요. 2008년 4월, 이 프로젝트는 Spring Security 2.0.0이라는 이름으로 Spring 포트폴리오에 공식적으로 포함되었죠! 🎉
Spring Security가 해결하는 문제들 🔧
인증(Authentication) 문제: "너 누구야?" 라는 질문에 답하는 것
- 다양한 인증 방식 지원 (Form 로그인, JWT, OAuth2 등)
- 비밀번호 암호화 및 관리
- Remember-Me 기능
인가(Authorization) 문제: "너 이거 할 수 있어?" 라는 질문에 답하는 것
- URL 기반 접근 제어
- 메소드 수준의 보안 (@PreAuthorize, @PostAuthorize)
- 역할 기반 접근 제어 (RBAC)
보안 위협 방어:
- 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();
}
주의사항 및 팁 💡
⚠️ 이것만은 주의하세요!
CSRF 토큰 설정
- REST API에서는 보통 비활성화하지만, 웹 애플리케이션에서는 반드시 활성화
- JWT를 사용할 때는 CSRF를 비활성화해도 안전
비밀번호 인코더
- 절대 평문으로 저장하지 마세요!
- BCryptPasswordEncoder 사용 권장
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
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