Spring Security + JWT 을 알아보자!
1. Spring Security란
❓
- 일반적인 공격 대한 인증, 권한 부여 및 보호 기능을 제공하는 프레임 워크
- Servlet, Reactive 애플리케이션 모두 보호 가능
- 다양한 필터를 사용하여 custom 이 가능하다.
2. Filter ?
❓ Filter ?
- 클라이언트의 요청에 대해서 DispathcherServlet을 통과하게 되고, 이후에 각 요청을 담당하는
Controller
이전에 대해 사전에 걸러내는 역할 (CORS, XSS 방어, 인코딩 변환 등 )
💡 Spring Security Filter Chain 종류
- SecurityContextPersistentFilter : SecurityContextRepository에서 SecurityContext를 가져와서 SecurityContextHolder에 주입하거나 반대로 저장하는 역할을 합니다.
- LogoutFilter : logout 요청을 감시하며, 요청시 인증 주체(Principal)를 로그아웃 시킵니다.
- UsernamePasswordAuthenticationFilter : login 요청을 감시하며, 인증 과정을 진행합니다.
- DefaultLoginPageGenerationFilter : 사용자가 별도의 로그인 페이지를 구현하지 않은 경우, 스프링에서 기본적으로 설정한 로그인 페이지로 넘어가게 합니다.
- BasicAuthenticationFilter : HTTP 요청의 (BASIC)인증 헤더를 처리하여 결과를 SecurityContextHolder에 저장합니다.
- RememberMeAuthenticationFilter : SecurityContext에 인증(Authentication) 객체가 있는지 확인하고 RememberMeServices를 구현한 객체 요청이 있을 경우, RememberMe를 인증 토큰으로 컨텍스트에 주입합니다.
- AnonymousAuthenticationFilter : 이 필터가 호출되는 시점까지 사용자 정보가 인증되지 않았다면 익명 사용자로 취급합니다.
- SessionManagementFilter : 요청이 시작된 이후 인증된 사용자인지 확인하고, 인증된 사용자일 경우SessionAuthenticationStrategy를 호출하여 세션 고정 보호 매커니즘을 활성화 하거나 여러 동시 로그인을 확인하는 것과 같은 세션 관련 활동을 수행합니다.
- ExceptionTranslationFilter : 필터체인 내에서 발생되는 모든 예외를 처리합니다.
- FilterSecurityInterceptor : AccessDecisionManager로 권한부여처리를 위임하고 HTTP 리소스의 보안 처리를 수행합니다.
3. Spring Security?
💡 흐름도
- client가 사용자 ID과, 비밀번호와 함께 인증 요청 (Http Request)
AuthenticationFilter
가 해당 요청을 가로체어 해당 정보로 UsernamePasswordAuthenticationToken
인증 객체 생성
AuthenticationManager
의 구현체인 ProviderManager
에게 UsernamePasswordAuthenticationToken
객체를 전달
- 다시
AuthenticationProvider
에 UsernamePasswordAuthenticationToken
객체를 전달
- 실제 저장소에 저장되어 있는 사용자 인증정보를 가져오는
UserDetailsService
에 사용자 정보(ID)를 전달
- 넘겨받은 사용자 정보를 통해 실제 저장소에서 사용자 정보를 찾아
UserDetails
객체 생성
AuthenticationProvider
는 UserDetails
를 넘겨받고 사용자 정보를 비교하여 인증 시도
- 인증이 완료되면 권한 등의 사용자 정보를 담은
Authentication
객체를 반환
- 다시 최초의
AuthenticationFilter
에 Authentication
객체 반환
Authentication
객체를 SecurityContext
에 저장
최종
SecurityContextHolder
는 세션 영역에 있는 SecurityContext
에 Authentication
객체를 저장
- 세션에 사용자정보를 저장한다는 것은 스프링 시큐리티가 전통적인 세션-쿠키 기반의 인증 방식을 사용한다는 것을 의미
4. JWT ?
❓
- Json Web Token
- RFC 7519 웹 표준
- Json 객체를 사용해서 토큰 자체에 정보들을 저장하고 있는 web token
💡 jwt 구조
- header
- signature를 해싱하기 위한 알고리즘 정보
- payload
- 서버-클라이언트가 주고받는 시스템에서
실제로 사용하기 위한 데이터
- signature
- 서버가 해당 토큰이 유효한 토큰인지 검증 문자열
💡 장/단점
장점
중앙의 인증서버
와 데이터
스토어에 대한 의존성이 없기
때문에 수평적 확장에 유리
- Base64 URL Safe Encoding > URL, Cookie, Header 모두 사용 가능
단점
Payload의 정보가 많아지면
트레픽의 크기
가 커질
수 있으므로 데이터 설계 고려가 필요
토큰
이 서버에 저장되지 않고, 클라이언트쪽에 저장
되므로 서버에서는 클라이언트의 토큰을 조작할 수 없음
💡 jwt 흐름도
서버
에 로그인 요청(인증)이 완료되면 클라이언트에게 사용자를 구분할 수 있는 정보를 담은 JWT를 생성하여 전달
- 이후
클라이언트
는 이 JWT를 헤더에 담아서 요청 시도
서버
는 해당 요청이 권한이 필요할 때 마다 API 서버는 헤더에 담긴 JWT 값을 확인하고 권한이 있는 사용자지 확인하고 리소스를 제공
📌 여담
📚 참고