티스토리 뷰

728x90

🔧 환경


- java 1.8 

- spring

- jsp

- javascript

- sweetalert

 

🔎 요구사항


- 사용자의 마지막 동작으로 부터 1시간이 지나면 세션을 만료하되, 만료되기 1분전에 세션 만료 알림을 띄어 연장할 수 있어야 한다.

 

🔎 idea


- server에 filter를 등록하여 요청이 올 때마다 response에 마지막 요청시간을 cookie를 저장하고,

front단에서는 cookie를 1초마다 확인하여 세션 만료 1시간 전 알림을 보내준다.

- 세션 만료 시간 =  마지막 요청 시간 + 1시간

 

📌 구현


💻 server

1. web.xml 설정

- web.xml에 기본 세션 만료 시간을 설정한다.

- web.xml에 설정한 timeout의 단위는 '분' 이다.

 <session-config>
    <session-timeout>60</session-timeout>
 </session-config>

2. filter 생성 및 등록

1) filter 생성

- 서버시간+타임아웃을 더한 시간을 sessionExpiry라는 쿠키에 담는다.

package com.egovframework.common.filter;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
public class SessionTimeoutCookieFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
		
        //쿠키에 저장하는 시간의 단위는 millisecond
        //session만료시간 = 서버시간 + web.xml에 설정한 시간 *1000 (단위를 맞추기 위해 *1000) 
        long sessionExpiryTime = System.currentTimeMillis() + request.getSession().getMaxInactiveInterval() * 1000;
		//새로운 쿠키를 생성한다. 쿠키명 : sessionExpiry
        Cookie sessionExpiryCookie = new Cookie("sessionExpiry", Long.toString(sessionExpiryTime));
        sessionExpiryCookie.setPath("/BotMain_VM");
        //response에 쿠키를 담아준다.
        response.addCookie(sessionExpiryCookie);
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

2) filter 등록

- web.xml에 위에서 만든 필터를 등록해준다.

  <filter>
    <filter-name>SessionTimeoutCookieFilter</filter-name>
    <filter-class>com.egovframework.common.filter.SessionTimeoutCookieFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>SessionTimeoutCookieFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

 

🎈 front

- 해당 소스는 모든 페이지마다 적용해야하므로, 모든 페이지에 공통으로 들어가는 header.jsp에다 작성했다

- server에서 저장한 쿠키 sessionExpiry와 클라이언트 시간을 비교하여 세션 만료 여부 및 알림 여부를 결정한다.

- sessionAlertCheck와 isSessionExpired는 합칠 수 있을 것 같은데..이름이 명확한게 좋을 것 같아서...따로 나뒀다🙄

함수명 설명
sessionAlertCheck(offset) 세션 만료 offset만큼의 시간전에 사용자에게 알림을 줘야하는지를 판단한다.
isSessionExpired 세션이 만료되었는지를 판단한다.
alertSessionExpiredAndLogout 세션이 만료되었다는 알림 후 메인 페이지로 이동한다.
checkSessionExpired setInterval에 등록하여 세션 만료 여부와 알림여부를 확인 후 알림을 준다.
/**
 * @name sessionAlertCheck
 * @param offset(millisecond)
 * @description 세션 만료 되기 전에 알림 여부 확인
 *	offset 만큼 세션만료 되기 전에 알림을 줘야하는지 판단한다.
 *	예) offset=1000*10 인경우 세션 만료 1시간 전에 알림 여부 true를 반환 
 * @author injeong.cheon
 * @returns {boolean}
 */
	const sessionAlertCheck = (offset) => {
		const sessionExpiry = Math.abs(getCookie('sessionExpiry')) - (offset);
		const time = new Date().getTime();
		if ( time - sessionExpiry > 0 ) {
			return true;
		}
		return false;
	}
/**
 * @name isSessionExpired
 * @description 세션 만료 여부 확인
 * @author injeong.cheon
 * @returns {boolean}
 */
	const isSessionExpired = () => {
		const sessionExpiry = Math.abs(getCookie('sessionExpiry'));
		const time = new Date().getTime();
		if ( time - sessionExpiry > 0) {
			return true;
		}
		return false;
	}
/**
 * @name alertSessionExpiredAndLogout
 * @author injeong.cheon
 * @description 세션 종료 알림 후 로그아웃 or 팝업창 닫기
 */
	const alertSessionExpiredAndLogout = () => {
		let text = '세션이 종료 되어 로그인 페이지로 이동합니다.';
		let action = () => {
			location.href = '/';
		}
		if (opener) {
			text = '세션이 종료 되어 페이지를 닫습니다.';
			action = () => {
				window.close();
			}
		}

		swal({
			title : "알림",
			icon  : "warning",
			text : text,
			closeOnClickOutside : false
		}).then(function(){
			action();
		});
	}

/**
 * @name checkSessionExpired
 * @author injeong.cheon
 * @description 세션 만료 전 알림
 */
	const checkSessionExpired = () => {
    	//알림 여부를 판단한다.
		const alertFlag = sessionAlertCheck(1000 * 60);
		if (alertFlag === true) {
			if (isSessionExpired()) {
				alertSessionExpiredAndLogout();
			} else {
				swal('알림', "1분 후 세션이 만료됩니다. 세션을 연장하시겠습니까? ", "warning", {
					buttons: ["취소", "연장"],
				}).then(function (willExtend) {
                	//연장을 선택한 경우 쿠키를 새롭게 셋팅해준다. 현재시간 + 한시간
					if (willExtend) {
						setCookie('sessionExpiry', new Date().getTime() + (1000*10*60));
					//연장하지 않는 경우에는
                    } else {
                  		//interval을 clear하고
						clearInterval(checkSessionInterval);
                        //세션종료 타이머를 생성한다.
                        //timeout = 세션만료 시간 - 현재시간 
						const timeout = getCookie('sessionExpiry') - new Date().getTime();
						setTimeout(()=> {
							alertSessionExpiredAndLogout();
						},timeout);
					}
				});
			}
		}
	}
    
    //세션 만료시간을 지속적으로 확인 할 수 있게 interval설정
	const checkSessionInterval = setInterval(checkSessionExpired, 1000);

 

🧐개선점 / 생각 해봐야할 점

- 연장 취소를 누른 경우 타이머를 삭제했기 때문에 해당 페이지에서 타이머 만료 전에 서버에 새로운 요청을 보내도 세션은 연장되지 않는다.

- 연장 취소를 누른 경우 세션 만료 전 다른 페이지로 이동하면 타이머가 다시 실행된다. 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함