Skip to content
isdnetworks
Go back

재시작했더니 다 로그아웃됐다

배포하고 서버를 다시 띄웠더니 로그인이 풀렸다는 문의가 들어왔다. 작성 중이던 글이 날아갔다는 얘기도 있었다.

Table of contents

Open Table of contents

세션이 어디에 있나

로그인 상태는 HttpSession 에 있었고 그 값은 Tomcat 프로세스 메모리에 있다. 프로세스가 끝나면 같이 사라진다.

배포할 때마다 service tomcat restart 를 치니 그때마다 전원이 로그아웃된다. 낮에 배포하면 그 시각에 쓰고 있던 사람이 전부 겪는다.

파일로 남기는 설정

Tomcat 의 StandardManager 는 종료할 때 세션을 SESSIONS.ser 로 저장하고 시작할 때 되읽는다. 정상 종료면 세션이 살아남는다.

다만 조건이 붙는다. kill -9 로 끊으면 저장이 안 된다. 세션에 담긴 객체가 Serializable 이어야 한다. 파일이 그 서버에만 있으니 한 대여야 한다. 서버를 두 대로 늘리면 한쪽에서 만든 세션을 다른 쪽이 모른다.

세션에 든 것을 줄였다

세션에 무엇을 넣었는지 다 적어 봤다. 사용자 식별자와 이름과 등급 말고도 장바구니 객체와 검색 조건 객체가 들어 있었다.

뒤의 둘이 Serializable 이 아니라 저장할 때 NotSerializableException 이 났다. 식별자만 남기고 나머지는 필요할 때 MySQL 에서 다시 조회하게 바꿨다.

session.setAttribute("userId", userId);

이름과 등급은 조회하면 나온다. 매번 조회하는 것이 부담이 되면 그때 다시 생각할 일이고, 지금은 세션에 상태를 쌓지 않는 쪽이 나아 보였다. 세션에 든 것이 적을수록 잃을 것이 적다.

쿠키로 옮기고 배포 시각도 바꿨다

로그인 유지만이라도 프로세스와 무관하게 만들었다. 서명이 든 문자열을 쿠키로 주고 서버는 그 값을 확인만 한다.

String sig = hmac(userId + "|" + expire, SECRET);
String token = userId + "|" + expire + "|" + sig;

받은 값에서 HMAC 서명을 다시 계산해 같은지 본다. 다르면 위조다. 값을 그대로 믿으면 아무나 남의 식별자를 적어 보낼 수 있다. 쿠키에 HttpOnly 도 붙여 JavaScript 가 못 읽게 했다.

작성 중이던 글은 다른 문제였다. 로그인이 유지돼도 화면 내용은 새로고침되면 사라진다. jQuery 로 30초마다 임시 저장하게 하고, 다음에 글쓰기 화면에서 임시 저장분이 있는지 물어보게 했다.

기술 말고 하나 더 있었다. 낮에 배포하면 영향받는 사람이 많다. Apache 액세스 로그를 시간대별로 세니 새벽 4시가 가장 적었고 급하지 않은 배포는 그 시간대로 정했다.

정리


Share this post on:

Previous Post
지워도 되는지 아무도 몰랐다
Next Post
성공이라는데 내용이 없었다