Ryan's Log

Java Web 세션 만료 추적 본문

카테고리 없음

Java Web 세션 만료 추적

Ryan c 2017. 12. 21. 14:07
728x90

Java Web 세션 만료 추적 

(Tracking session expiration in browser)



흔히 은행 인터넷뱅킹에서 사용하듯 세션이 만료되기 전 브라우저에서 만료예정임을 알려주고 연장하거나 로그아웃됨을 알리고 로그인 화면으로 이동시킬 수 있는데 이를 구현하는 매우 좋은 방법을 남긴다.


세션 만료 추적을 처음 고민할 때 가장 먼저 생각하는 방법은...

브라우저에서 타이머를 구현하여 서버에 주기적으로 세션유지 상태를 점검하는 요청을 보내고자 할 텐데

이 방법에 몇가지 문제가 있다.


-. 서버에 주기적인 요청을 해야하며

-. 세션을 사용하지않는 요청(session = false)으로 구현해야 하지만

-. 혹 만료시간등 예측을 해야한다면 심지어 세션에 접근해야 하는데 이로인해 세션 만료시간은 연장될 것이고


이는 답이 아니다.



만약 서버시간과 세션만료예정시간을 정확히 알수 있다면 브라우저 타이머를 이용하여 주기적으로 세션 만료 여부를 검사하여 사용자에게 알리고 로그아웃 할 수 있을 것이다.


서버시간에 브라우저에서 흐른 시간을 더한 시간이 세션만료예정시간을 지난경우 로그아웃됨을 알리는것이다.


이 방식을 위해 서버로의 모든 요청시에 서버시간과 세션만료예정시간을 얻어올 수 있는지 여부 확인이 필요하다.

새로 구현할 경우 이를 구현하겠지만, 구 시스템은 모든 요청에 위 두 시간값을 얻어올 수 있는 코드를 심을 수 있는지 여부 말이다.



쿠키를 사용할 경우 매 요청시마다 서버시간 및 세션만료예정시간을 자연스럽게 얻을 수 있다.

아니 정확하게는 Servlet Filter를 이용하여 쿠키에 이 두시간을 기록하는 것이다.


Java World -  HOW-TO - Tracking session expiration in browser 참조



SessionTimeoutCookieFilter.java

public class SessionTimeoutCookieFilter implements Filter {

	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        long serverTime = System.currentTimeMillis();
        long sessionExpiryTime = serverTime + request.getSession().getMaxInactiveInterval() * 1000;
        Cookie cookie = new Cookie("latestTouch", "" + serverTime);
        cookie.setPath("/");
        response.addCookie(cookie);
        cookie = new Cookie("sessionExpiry", "" + sessionExpiryTime);
        cookie.setPath("/");
        response.addCookie(cookie);
        filterChain.doFilter(servletRequest, servletResponse);
	}

	@Override
	public void destroy() {
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
	}
	
}


web.xml

<filter>
    <filter-name>SessionTimeoutCookieFilter</filter-name>
    <filter-class>
        gmes.smartfactory.common.core.SessionTimeoutCookieFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>SessionTimeoutCookieFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>



이를 구현하면 즉시 크롬 개발자 도구 Application탭에서 쿠키 정보를 확인할 수 있다.






이후 브라우저에서 동작할 화면에 다음 두 함수을 구현한다.


var setTimeOffsetBetweenServerAndClient = function(){
	var latestTouch = getCookie('latestTouch');
	latestTouch = latestTouch==null ? null : Math.abs(latestTouch);
	var clientTime = (new Date()).getTime();
	var clientTimeOffset = clientTime - latestTouch;
	setCookie('clientTimeOffset', clientTimeOffset);
}

이 함수는 서버시간과 브라우저의 시간을 동기화 하는데 필요한 offset이다.

서버시간과 브라우저 시간이 동일 하지 않기 때문이다.

향후 이 offset을 서버시간에 차감하여 보다 현실적으로 세션만료예정시간과 비교하기 위함이다.

이는 화면 초기화 중에 한번 호출한다.



var isSessionExpired = function(offset){ var sessionExpiry = Math.abs(Util.getCookie('sessionExpiry')); var timeOffset = Math.abs(Util.getCookie('clientTimeOffset')); var localTime = (new Date()).getTime(); setCookie('remainTime', (sessionExpiry - (localTime - timeOffset))); return localTime - timeOffset > (sessionExpiry-(offset||0)); }

이 함수는 현재 시점에 세션이 만료된 상태인지 여부를 반환한다.

이를 응용하면 세션 만료까지 얼마나 남았는지를 알 수 있다. (인터넷뱅킹 로그인 연장기능 처럼)




다음으로 브라우저에 타이머를 구현한다.

function checkSessionExpired(){
	var isExpired = isSessionExpired(-5*1000);	//세션만료예정시간을 5초 앞당겨서 검사
	if(isExpired === true){
		alert('Session Expired. Please login.');
		goLogin();
	}else{
		setTimeout('checkSessionExpired()', 10*1000);	//10초에 한번씩 티이머 반복
	}
}







728x90