JWT(2)
TIL: Spring Security 동작 원리와 JWT 기반 인증 구현
핵심 전략
- Access Token: 유효기간을 매우 짧게 설정(수분 ~ 1시간)하여 탈취 시 피해를 최소화.
- Refresh Token: 유효기간을 길게 설정(수일 ~ 수주)하고 DB에 저장하여 관리. Access Token 재발급 시에만 사용.
서버 사이드 구현 (Spring Security)
동작 원리 및 필터 체인
Spring Security의 Filter Chain 내부에서 JWT가 어떻게 동작하는지 설명합니다.
- 로그인 시 (
JwtAuthenticationFilter):/api/v1/auth/login요청 시 동작. 인증 성공 시successfulAuthentication메서드에서 Access/Refresh Token을 모두 생성하여 클라이언트에 반환하고, Refresh Token은 DB에 업데이트합니다. - API 요청 시 (
JWTVerificationFilter): 헤더에 포함된 토큰을 검증합니다. 유효하면SecurityContext에 인증 정보를 저장하여 이후 리소스 접근을 허용합니다. - 예외 처리: 특정 경로(예:
/api/v1/auth/refresh)는 토큰 검증 필터를 타지 않도록 설정하거나 별도 로직으로 처리합니다.
주요 Endpoint 구현
- 로그인 (
/login):Access Token(1시간)과Refresh Token(1일) 동시 발급.- DB의 Member 정보에 Refresh Token 저장.
- 토큰 갱신 (
/refresh):- 헤더의
Refresh-Token을 받아 검증(DB 값과 일치 여부, 유효성 확인). - 검증 성공 시 새로운 Access/Refresh Token을 발급하고 DB를 업데이트.
- 헤더의
- 로그아웃 (
/logout):- DB에 저장된 Refresh Token을 삭제(null 처리)하여 더 이상 토큰 갱신이 불가능하게 만듦.
클라이언트 사이드 구현 (Vue.js & Axios)
토큰 관리 (Store)
jwt-decode라이브러리를 사용하여 토큰 내부의 정보(Payload)를 디코딩해 사용자 정보를 관리합니다.- 상태 관리 저장소(Store)에 토큰을 저장하고 로그인/로그아웃 상태를 갱신합니다.
Axios Interceptors (핵심 로직)
API 요청과 응답을 가로채어 인증 로직을 자동화합니다.
- Request Interceptor:
skipAuth옵션이 없는 일반 요청에는Authorization헤더에 Access Token을 자동으로 포함합니다.
- Response Interceptor (에러 핸들링):
- 서버로부터
401 Unauthorized에러와 함께TOKEN_ERROR메시지를 받으면 토큰 만료로 간주합니다. - 자동 갱신 로직:
useTokenRefresh를 호출하여 토큰 재발급을 시도합니다.- 성공 시: 실패했던 원래의 요청(
originalRequest)을 새 토큰으로 재시도합니다. - 실패 시: Refresh Token도 만료된 것이므로 강제 로그아웃 처리하고 로그인 페이지로 이동합니다.
- 성공 시: 실패했던 원래의 요청(
- 서버로부터
전체 인증 흐름 요약 (Scenario)
- 로그인: 사용자가 ID/PW 전송 → 서버가 검증 후 Access/Refresh Token 발급 및 DB 저장.
- API 사용: 클라이언트는 API 호출 시 Access Token 사용.
- 토큰 만료: 시간 경과로 Access Token 만료 시 서버는
401 Error반환. - 토큰 갱신: 클라이언트는
Refresh Token을 실어/refresh요청 → 서버는 검증 후 새 토큰 발급. - 재요청: 클라이언트는 새 Access Token으로 원래 하려던 요청을 재수행.
- 로그아웃: 클라이언트가 로그아웃 요청 시 서버 DB의 Refresh Token 삭제.
결론 및 참고사항
- 보안성: Refresh Token을 통해 Access Token의 수명을 짧게 가져감으로써 보안성을 높였습니다. 단, Refresh Token 자체도 탈취될 위험이 있으므로 HTTPS 사용 및 적절한 저장소 관리가 필요합니다.
- 사용자 경험: Axios Interceptor를 통해 토큰 만료 시 사용자가 인지하지 못하게 백그라운드에서 토큰을 갱신하므로 끊김 없는 서비스 이용이 가능합니다.
- 구현 포인트:
SecurityFilterChain구성 시 필터 순서와skipAuth같은 예외 처리가 꼼꼼하게 구현되어야 무한 루프나 인증 오류를 방지할 수 있습니다.