| 제목 | Java Spring 세션 남은 시간 표시 | ||||||
| 글쓴이 | 이지섭 | 작성일 | 2025-06-29 | 수정일 | 2025-07-26 | 조회수 | 660 |
Java, Spring 에서 로그인 세션의 남은 시간을 보여주는 것이다.
Spring Boot 에서는 좀 다른 방식으로 구현할 수 있지만, Spring framework 에서 구현하는 방식을 설명한다. web.xml 파일을 이용한다.
*.do 또는 /api/* 백앤드 호출에서 필터를 적용하여, 로그인 세션의 종료될 시간을 쿠키에 세팅하고, 프론트 단에서 쿠키 값을 읽어서 남은 시간을 표시한다.
SessionTimeoutCookieFilter 필터 클래스에서 @Component("sessionTimeoutCookieFilterBean") 으로 선언한다.
Spring에서 Filter에 DI 를 적용하려면 DelegatingFilterProxy 를 사용해야 한다. web.xml 의 filter 의 filter-class 에서. DI 는 세션의 유지 시간을 구해오는 서비스를 Autowired 하기 위함이다.
본 소스에서는 personalInfoService.selectSystemEnv(); 으로 세션 유지 시간을 구해온다.
package isry.itgcms.sysmgmt.util;
import java.io.IOException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
//import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import isry.itgcms.sysmgmt.personalinfo.service.PersonalInfoService;
@Component("sessionTimeoutCookieFilterBean")
public class SessionTimeoutCookieFilter implements Filter {
@SuppressWarnings("unused")
private FilterConfig config;
@Autowired
private PersonalInfoService personalInfoService;
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
//HttpServletRequest httpRequest = (HttpServletRequest) request;
int sessionTime = 30;
try {
Map map = personalInfoService.selectSystemEnv();
sessionTime = Integer.parseInt(map.get("SESIN_TMOUT_MINUTES"));
} catch (Exception e) {
e.printStackTrace();
}
long sessionDurationTime = System.currentTimeMillis() + sessionTime * 60 * 1000;
Cookie cookie = new Cookie("sessionDurationTime", "" + sessionDurationTime);
//cookie.setSecure(true);
cookie.setPath("/");
httpResponse.addCookie(cookie);
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
public void destroy() {
}
}
아래는 web.xml 파일에서 필터를 등록하는 부분이다. 필터 클래스를 org.springframework.web.filter.DelegatingFilterProxy 으로 하고, @Component("sessionTimeoutCookieFilterBean") 으로 선언했던 필터 Bean 을 등록한다.
url-pattern 에는 *.do 또는 /api/* 등의 패턴을 적용한다. 선택적인 사항이다. 백앤드 프로그램이 호출될 때마다 세션 유지 시간이 재 설정되는 것이다.
<filter>
<filter-name>sessionTimeoutCookieFilterBean</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported> <!-- Support Async -->
</filter>
<filter-mapping>
<filter-name>sessionTimeoutCookieFilterBean</filter-name>
<url-pattern>*.do</url-pattern> <!-- Your Choice 1 -->
<url-pattern>/api/*</url-pattern> <!-- Your Choice 2 -->
</filter-mapping>
아래는 프론트 단의 소스이다. 쿠키에서 세션이 종료될 시간을 읽어와서 남은 시간을 표시해준다.
<!DOCTYPE html>
<html>
<head>
<title>Time Left</title>
<script type="text/javascript">
var timeInterval = 1000; // 1-second interval calls
var timer;
var timerArr = new Array();
var timeGap = 0;
async function init() {
const response = await fetch('/getCurrentTime.do');
console.log("response", response);
const systemTime = await response.json();
console.log("systemTime", systemTime);
// Browser time
const localTime = new Date().getTime();
console.log("localTime", localTime);
timeGap = Number(systemTime) - localTime;
console.log("timeGap", timeGap);
showRemaining();
timer = setInterval(showRemaining, timeInterval); // 1-second interval calls
timerArr.push(timer);
}
function showRemaining() {
var timeRemaining = Number(getCookie("sessionDurationTime")) - new Date().getTime() - Number(timeGap);
//console.log("sessionDurationTime", getCookie("sessionDurationTime"));
//console.log("unix time", new Date().getTime());
//console.log("timeRemaining", timeRemaining);
if (timeRemaining < timeInterval) {
for (var i = 0; i < timerArr.length; i++) {
clearInterval(timerArr[i]);
}
timerArr = new Array();
setTimeout(function() {
alert("Session expired.");
}, 1000);
return;
}
var timeHour = Math.floor(timeRemaining / 1000 / 60 / 60);
var timeMin = Math.floor((timeRemaining / 1000 / 60) % 60);
var timeSec = Math.floor((timeRemaining / 1000) % 60);
const formattedHours = String(timeHour).padStart(2, '0');
const formattedMinutes = String(timeMin).padStart(2, '0');
const formattedSeconds = String(timeSec).padStart(2, '0');
document.getElementById("timeRemaining").innerHTML
= formattedHours + ":" + formattedMinutes + ":" + formattedSeconds;
}
function getCookie(psName) {
var vsCookie = document.cookie + ";";
var vaItems = vsCookie.split(";");
var vnItemLen = vaItems.length;
var item = null;
var voItemInfo = null;
for (var i = 0; i < vnItemLen; i++) {
item = vaItems[i];
voItemInfo = item.split("=");
if (psName == voItemInfo[0].trim()) {
return unescape(voItemInfo[1]);
}
}
return "";
}
</script>
</head>
<body onload="init();">
Time remaining : <span id="timeRemaining"></span>
</body>
</html>
const response = await fetch('/getCurrentTime.do');
위 코드는 로컬 컴퓨터의 시간과 실제 시간과의 차이를 상쇄하기 위해서
서버의 현재 시간 값을 구해오는 부분이다.
.do 의 소스는 아래에 있다.
package isry.itgcms.sysmgmt.util;
import java.time.Instant;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class CurrentTime {
@RequestMapping(value = "/getCurrentTime.do")
@ResponseBody
public Long getCurrentTime(HttpServletRequest request, HttpServletResponse response) throws Exception {
long timestamp = System.currentTimeMillis();
System.out.println("current timestamp (milli seconds): " + timestamp);
Instant timestamp1 = Instant.now();
System.out.println("current timestamp: " + timestamp1);
// Convert timestamp to milli seconds
long milliseconds = timestamp1.toEpochMilli();
System.out.println("current timestamp (milli seconds): " + milliseconds);
return milliseconds;
}
}
스프링 부트에서는 아래와 같이 필터를 등록할 수 있다.
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import isry.itgcms.sysmgmt.util.SessionTimeoutCookieFilter;
@Configuration
public class MyFilterConfig {
@Bean
public FilterRegistrationBean sessionTimeoutCookieFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean<>();
registration.setFilter(new SessionTimeoutCookieFilter());
registration.addUrlPatterns("*.do");
registration.addUrlPatterns("/api/*");
registration.setAsyncSupported(true);
return registration;
}
}
Async Supported 는 필수 사항은 아니지만, 경우에 따라서는 필요할 수도 있습니다.
[ 참조한 페이지 ]
| |||||||
| 첨부파일 | CurrentTime.java (1,026 byte) timeLeft.html (2,553 byte) SessionTimeoutCookieFilter.java (1,932 byte) | ||||||
로그인 | Language : |