
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
package com.takensoft.common.util;
import jakarta.servlet.http.HttpSession;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author takensoft
* @since 2025.03.21
* @modification
* since | author | description
* 2025.03.21 | takensoft | 최초 등록
* 2025.05.29 | takensoft | Redis 통합 중복로그인 관리
*
* 세션 로그인 방식의 유틸리티 - Redis 통합
*/
@Component
public class SessionUtil {
private final Map<String, HttpSession> sessionMap = new ConcurrentHashMap<>();
private final RedisTemplate<String, String> redisTemplate;
public SessionUtil(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 세션 등록 - Redis 연동
* 기존 세션 있으면 강제 로그아웃 후 새 세션 등록
*/
public synchronized void registerSession(String mbrId, HttpSession newSession) {
try {
// 1. 기존 메모리 세션 처리
HttpSession oldSession = sessionMap.get(mbrId);
if (oldSession != null && oldSession != newSession) {
try {
oldSession.invalidate();
} catch (IllegalStateException e) {
}
}
// 2. 새 세션을 메모리에 등록
sessionMap.put(mbrId, newSession);
// 3. Redis에 세션 정보 저장 (중복로그인 관리용)
String sessionKey = "session:" + mbrId;
redisTemplate.opsForValue().set(sessionKey, newSession.getId(),
Duration.ofSeconds(newSession.getMaxInactiveInterval()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 세션 ID로 세션 무효화
*/
public void invalidateSessionById(String sessionId) {
try {
boolean found = false;
// 메모리에서 해당 세션 ID를 가진 세션 찾아서 무효화
sessionMap.entrySet().removeIf(entry -> {
HttpSession session = entry.getValue();
if (session != null && session.getId().equals(sessionId)) {
try {
session.invalidate();
return true;
} catch (IllegalStateException e) {
return true;
}
}
return false;
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 사용자별 세션 제거 - Redis 연동
*/
public void removeSession(String mbrId) {
try {
// 1. 메모리 세션 무효화
HttpSession session = sessionMap.get(mbrId);
if (session != null) {
try {
session.invalidate();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
sessionMap.remove(mbrId);
// 2. Redis에서도 제거
String sessionKey = "session:" + mbrId;
redisTemplate.delete(sessionKey);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 전체 세션 무효화 - Redis 연동
*/
public void invalidateAllSessions() {
try {
// 1. 모든 메모리 세션 무효화
for (Map.Entry<String, HttpSession> entry : sessionMap.entrySet()) {
HttpSession session = entry.getValue();
if (session != null) {
try {
session.invalidate();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
sessionMap.clear();
// 2. Redis에서 모든 세션 키 삭제
try {
var sessionKeys = redisTemplate.keys("session:*");
if (sessionKeys != null && !sessionKeys.isEmpty()) {
redisTemplate.delete(sessionKeys);
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 현재 활성 세션 수 조회
*/
public int getActiveSessionCount() {
return sessionMap.size();
}
/**
* 특정 사용자의 세션 존재 여부 확인
*/
public boolean hasActiveSession(String mbrId) {
HttpSession session = sessionMap.get(mbrId);
if (session == null) {
return false;
}
try {
// 세션이 유효한지 확인
session.getAttribute("mbrId");
return true;
} catch (IllegalStateException e) {
// 세션이 무효화됨
sessionMap.remove(mbrId);
return false;
}
}
/**
* Redis에서 세션 정보 확인
*/
public boolean isValidSessionInRedis(String mbrId, String sessionId) {
try {
String sessionKey = "session:" + mbrId;
String storedSessionId = redisTemplate.opsForValue().get(sessionKey);
return storedSessionId != null && storedSessionId.equals(sessionId);
} catch (Exception e) {
return false;
}
}
}