들어가며
토이 프로젝트의 유저 인증방식을 세션으로 선택한 후 내부동작을 탐색하며 작성하는 포스팅입니다.
세션 관리의 내부동작을 왜 찾아봤을까?
오해는 여기에서 시작되었습니다. 아래와 같은 코드를 작성 후 브라우저를 확인해 보았습니다.
public ResponseEntity<Void> demo(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("JSESSIONID", 1234);
return ResponseEntity.ok().build();
}
스프링에서 제공하는 `HttpServletRequest` 객체에 세션을 설정만 하면 브라우저에서 사진과 같이 쿠키가 설정되어 있는 모습을 확인할 수 있습니다.
당연히 Name, Value가 세션의 각각 Key, Value라고 생각하고(사실이 아니었지만) 1234라는 숫자가 어떻게 339829792367CFF6674AE630DC79A78C로 암호화되는 걸까 라는 생각으로 내부 구현을 확인하게 되었습니다.
getSession()에서 일어나는 일 (쿠키에 세션데이터가 없을 때)
`HttpServlertRequest.getSession()`메서드를 호출하면 HTTP 요청에 세션이 없다면 새롭게 생성해 줍니다. `HttpServlertRequest`의 구현체인 `Request`가 구현한 `getSession()`을 호출합니다.
- `Request`가 `MappingData`에게 `Context`를 요청합니다.
- `Request`가 `Context`에게 `Manager`를 요청합니다.
- `Request`가 `Manager`에게 `Session`을 요청합니다.
- `Session`은 `SecureRandom`에게 랜덤바이트코드를 요청합니다.
- `SecureRandom`은 `SHA1PRNG` 알고리즘을 통해 랜덤한 문자열을 생성 후 반환합니다.
그렇습니다. 브라우저의 Value에 나타난 값은 1234를 암호화 한 값이 아니라 스프링에서 생성한 랜덤한 sessionId입니다.
이후 `setAttribure("foo",1234)`를 호출하면 Session이 key, value 데이터(attribute)를 저장합니다. (e.g. "foo", 1234)
스프링 Session 관리 데이터 구조
상위 그림에서 보이는 `StandardManager`가 Tomcat이 동작한 이후에 생성된 Session 목록을 관리합니다. 새롭게 생성된 `session`은 `sessions`에 추가됩니다.
key는 sessionId(위에서 생성한 랜덤문자열)이며 value는 Map형태로 지니고 있습니다. 여러 유저들이 서버에 접근하거나, 브라우저에서 쿠키를 지우고 세션을 생성하면 `sessions`에 계속해서 `session`이 생성됩니다.
getSession()에서 일어나는 일 (쿠키에 세션데이터가 있을 때)
스프링컨테이너는 HTTP요청이 들어오면 HttpMessage에서 쿠키에 존재하는 sessionId를 읽어 들입니다. 이후 `StandardManager`가 소유한 `sessions`에서 해당하는 key값을 통해 session을 반환합니다.
브라우저에 노출되는 쿠키
스프링 컨테이너는 세션을 쿠키에 작성해 내려줄 때 기본값으로 JSESSIONID 문자열을 이용합니다. 당연하게도 `setAttribute()`에서 지정해 주는 key값과는 관계가 없습니다.
마치며
스프링에서 session을 어떻게 생성하고 관리하는지 알게 되었습니다.
읽어주셔서 감사합니다.
'Spring' 카테고리의 다른 글
쓰기, 읽기 전용 Multiple DataSource 설정하기 (1) | 2024.06.04 |
---|---|
Use Redis to Session Storage (0) | 2024.05.19 |
IP 기반 API 호출 횟수 제한 (1) | 2024.05.17 |
Caching In Spring With Multiple Redis Server (0) | 2024.04.24 |
분산 시스템 환경에서 Scheduler 단일 동작시키기 (0) | 2024.04.24 |