토큰&세션&JWT
1. 토큰 (Token)
- 정의: 토큰은 인증 정보와 기타 데이터를 포함한 문자열로, 사용자가 인증되었음을 나타내거나 특정 권한을 부여받았음을 증명하는 데 사용됩니다.
- 사용 예시:
- 웹 애플리케이션에서 사용자가 로그인하면 서버는 사용자를 인증하고, 토큰을 발급하여 사용자의 인증 상태를 유지합니다.
- 장점:
- 무상태(stateless) 성격으로 서버가 인증 정보를 직접 저장할 필요가 없습니다.
- 단점:
- 토큰이 만료되기 전까지는 유효하여, 해킹 시 악용될 수 있으므로 보관에 주의가 필요합니다.
2. 세션 ID (Session ID)
- 정의: 세션 ID는 서버가 생성하고 클라이언트와 연결하는 고유한 ID로, 주로 쿠키에 저장되며 사용자가 로그인한 이후 서버에서 사용자 상태를 유지하는 데 사용됩니다.
- 사용 예시:
- 사용자가 로그인하면 서버는 사용자 정보와 상태를 세션으로 저장하고, 세션 ID를 발급하여 클라이언트에 전달합니다. 클라이언트는 이후 요청 시 세션 ID를 쿠키로 서버에 전달하여 인증을 수행합니다.
- 장점:
- 세션에 사용자 정보를 저장하므로 사용자의 상태를 서버에서 쉽게 관리할 수 있습니다.
- 단점:
- 서버 메모리를 사용해 세션을 관리해야 하므로, 많은 사용자가 접속할 경우 성능에 영향을 줄 수 있습니다.
3. JSON 웹 토큰 (JWT, JSON Web Token)
- 정의: JWT는 JSON 객체를 기반으로 한 인코딩된 문자열 토큰으로, 사용자 인증 정보를 안전하게 표현하고 전달하기 위해 사용됩니다. JWT는 크게 **헤더(Header), 페이로드(Payload), 서명(Signature)**의 세 부분으로 구성됩니다.
- 구성:
- 헤더(Header): 토큰 타입(JWT)과 서명 알고리즘 정보가 담겨 있습니다.
- 페이로드(Payload): 사용자 정보나 기타 클레임(Claims, 데이터)을 포함합니다. 예를 들어, 사용자 ID, 권한, 만료 시간 등이 저장될 수 있습니다.
- 서명(Signature): 헤더와 페이로드를 해싱한 후 비밀 키를 이용해 서명하여, 데이터가 변조되지 않았음을 검증할 수 있습니다.
- 사용 예시:
- 사용자 인증 후 JWT를 클라이언트에 전달하고, 이후 요청마다 이 토큰을 전달받아 서버에서 유효성을 검증해 인증을 수행합니다.
- 장점:
- 서버가 상태를 관리하지 않아도 되므로 무상태 인증을 지원하고, 여러 서비스 간에 쉽게 전송할 수 있습니다.
- 단점:
- 토큰이 만료되기 전까지는 유효하므로, 중간에 탈취되면 악용될 위험이 있습니다. 서버가 토큰을 별도로 갱신하거나 검증할 수 없으므로 만료 전까지 계속 사용할 수 있습니다.
요약 비교
항목토큰세션 IDJSON 웹 토큰 (JWT)
목적 | 사용자 인증 또는 권한 증명 | 서버에서 사용자 상태 관리 | 사용자 인증, 정보 전송, 무상태 인증 |
저장 위치 | 주로 헤더(Authorization) 또는 쿠키에 저장 | 쿠키에 저장 | 헤더(Authorization) 또는 로컬 스토리지에 저장 |
유효성 관리 | 만료 전까지 유효, 서버에서 관리하지 않음 | 서버에서 세션 만료 시간 설정 | 토큰 내 만료 시간이 있지만 서버에서 추가 관리 가능 |
구성 요소 | 주로 단일 문자열 | 고유한 문자열 ID | 헤더, 페이로드, 서명으로 구성된 JSON 형식 인코딩 문자열 |
장점 | 서버 상태 관리 필요 없음, 다양한 방식으로 전송 가능 | 서버에서 사용자 상태 관리 가능 | 무상태 인증, 여러 서비스 간 전송 용이 |
단점 | 탈취 시 악용 위험 존재 | 많은 사용자를 처리 시 서버 메모리 소모, 확장성 문제 | 탈취 시 악용 위험, 만료 전까지 유효 |
이렇게 각 인증 방식은 목적과 용도에 맞게 선택하여 사용하며, 보안과 효율성을 고려하여 필요 시 병행해 사용할 수도 있습니다.
로그인 요청 처리
1. UsernamePasswordAuthenticationFilter
UsernamePasswordAuthenticationFilter는 사용자가 제출한 로그인 정보(사용자 이름과 비밀번호)를 처리하는 필터입니다. 사용자가 로그인 양식을 제출하면 이 필터가 호출되어 인증 절차가 시작됩니다.
- 주요 역할:
- 사용자의 아이디와 비밀번호를 기반으로 인증을 시도합니다.
- POST /login 요청을 감지하고, 사용자 정보를 UsernamePasswordAuthenticationToken 형태로 생성하여 다음 단계로 전달합니다.
- AuthenticationManager에게 UsernamePasswordAuthenticationToken을 전달하여 실제 인증을 위임합니다.
- 작동 방식:
- 사용자가 로그인 요청을 하면, UsernamePasswordAuthenticationFilter가 이를 가로챕니다.
- 로그인 요청에서 사용자 이름과 비밀번호를 추출합니다.
- 이 정보를 기반으로 UsernamePasswordAuthenticationToken 객체를 생성하여 인증 요청을 생성합니다.
- 생성된 인증 요청은 AuthenticationManager로 전달됩니다.
2. AuthenticationManager
AuthenticationManager는 실제 인증을 수행하는 인터페이스로, 전달받은 Authentication 객체를 검사하고 인증 여부를 판단하여 결과를 반환합니다.
- 주요 역할:
- UsernamePasswordAuthenticationFilter가 전달한 Authentication 객체를 받아 인증을 처리합니다.
- 다양한 AuthenticationProvider와 협력하여 여러 방식의 인증을 처리할 수 있습니다.
- 작동 방식:
- AuthenticationManager는 전달받은 Authentication 객체를 하나 이상의 AuthenticationProvider에 위임하여 인증을 시도합니다.
- AuthenticationProvider는 인증 로직을 처리하고, 인증에 성공하면 인증된 Authentication 객체를 반환합니다.
- AuthenticationManager는 최종적으로 인증이 완료된 Authentication 객체를 SecurityContext에 저장하고, 인증 결과를 UsernamePasswordAuthenticationFilter에 반환합니다.
흐름 요약
- 사용자가 로그인 정보를 제출합니다.
- UsernamePasswordAuthenticationFilter가 이를 가로채어 UsernamePasswordAuthenticationToken을 생성하고, AuthenticationManager로 전달합니다.
- AuthenticationManager는 AuthenticationProvider에 위임하여 인증을 수행하고 결과를 반환합니다.
- 인증에 성공하면, SecurityContext에 사용자 정보를 저장하여 세션을 유지할 수 있게 합니다.
이로써 Spring Security는 사용자의 로그인 요청을 처리하고, 인증을 통해 보호된 리소스에 대한 접근을 제어할 수 있습니다.