Java 프레임워크 만들기 - JSP

자바 싱글톤 세션 매니저 만들기 - Java Singleton Session Manager, 이클립스(Eclipse)

carrotweb 2021. 4. 10. 18:08
728x90
반응형

1. "test2" 프로젝트의 "Java Resources"에서 "src/main/java"의 "com.hom.project.test2.service"에서 오른쪽 버튼을 클릭하여 컨텍스트 메뉴 [New > Class]를 클릭합니다.

"New Java Class"창의 "Name"에 "TestSessionManager"를 입력하고 "Modifiers"의 "final"를 체크하고 "Finish"버튼을 클릭합니다.

 

"test2" 프로젝트의 "Java Resources"에서 "src/main/java"의 "com.hom.project.test2.service"에 "TestSessionManager.java"파일이 생성됩니다.

 

싱글스톤 처리를 추가합니다.

/**
 * 생성자
 */
private TestSessionManager() {
}

/**
 * TestSessionCounter의 인스턴스를 가져옵니다.
 * @return TestSessionCounter 객체
 */
public static TestSessionManager getInstance() {
	return InClassInstance.testSingletonInstance;
}

private static class InClassInstance {
	private static final TestSessionManager testSingletonInstance = new TestSessionManager();
}

getInstance : InClassInstance을 통해 싱글톤으로 인스턴스를 가져옵니다.

 

세션 관리를 위해 세션 맵을 멤버 변수로 추가하고 세션 맵에 세션을 추가/삭제하고 가져오는 메서드를 추가합니다.

/**
 * 세션 맵
 */
private Map<String, HttpSession> sessionMap = new HashMap<>();

/**
 * 사용자 세션을 추가합니다. 
 * @param userId 사용자 Id
 * @param httpSession 사용자 세션
 * @return 추가 여부
 */
public boolean addSession(String userId, HttpSession httpSession) {
	boolean result = false;
	if (!sessionMap.containsKey(userId)) {
		if (null == sessionMap.put(userId, httpSession)) {
			result = false;
		} else {
			result = true;
		}
		System.out.println("Session Manager Count : " + sessionMap.size() + ", Add ID : " + userId + ", Session ID : " + httpSession.getId());
	}
	return result;
}

/**
 * 사용자 세션을 가져옵니다. 
 * @param id 사용자 Id
 * @return 사용자 세션
 */
public HttpSession getSession(String id) {
	HttpSession httpSession = null;
	if (sessionMap.containsKey(id)) {
		httpSession = sessionMap.get(id);
	}
	return httpSession;
}

/**
 * 사용자 세션을 제거합니다. 
 * @param userId 사용자 Id
 * @return 추가 여부
 */
public boolean removeSession(String userId) {
	boolean result = false;
	if (sessionMap.containsKey(userId)) {
		String sessionID = "";
		HttpSession httpSession = sessionMap.get(userId);
		if (null != httpSession) {
			sessionID = httpSession.getId();
			httpSession.invalidate();
			result = true;
		}
		sessionMap.remove(userId);
		System.out.println("Session Manager Count : " + sessionMap.size() + ", Remove ID : " + userId + ", Session ID : " + sessionID);
	}
	return result;
}

sessionMap : 로그인된 사용자 세션 맵으로 사용자 Id(userId)와 사용자 세션(httpSession)으로 관리합니다.

addSession : 세션 맵에 추가할 사용자 Id가 있는지 확인(containsKey)하고 없으면 추가합니다.

getSession : 세션 맵에 사용자 Id가 있으면 세션 맵에서 사용자 세션을 가져옵니다.

removeSession : 세션 맵에서 삭제할 사용자 Id가 있는지 확인(containsKey)하고 있으면 사용자 세션을 무효화(invalidate)하고 삭제합니다.

 

 

2. 로그인 처리를 하는 "TestLoginService.java"의 "process"메서드에 "TestSessionManager" 연동을 추가합니다.

public void process(HttpServletRequest request) throws UnsupportedEncodingException {
	String id = request.getParameter("id");
	String password = request.getParameter("pwd");
	System.out.println("id : " + id + ", password : " + password);

	HttpSession httpSession = request.getSession(false);
	httpSession.removeAttribute("auth");
	if ("testid".equals(id) && "testpwd".equals(password)) {
		UserVO user = new UserVO();
		user.setId(id);
		user.setName("사용자");
	
		TestSessionManager testSessionManager = TestSessionManager.getInstance();
		HttpSession userSession = testSessionManager.getSession(id);
		if (null == userSession) {
			httpSession.setAttribute("auth", user);
			testSessionManager.addSession(id, httpSession);
			request.setAttribute("errorMessage", "");
		} else {
			/**
			 * 중복 로그인 방지
			 * 1. 기존 접속자를 로그아웃 시키고 현재 접속자를 로그인 시킵니다.
			 * 2. 기존 접속자의 로그인을 유지하고 현재 접속자를 차단합니다.
			 */
			int processType = 1;
			if (1 == processType) {
				// 기존 접속자
				testSessionManager.removeSession(id);
				// 현재 접속자
				httpSession.setAttribute("auth", user);
				testSessionManager.addSession(id, httpSession);
				request.setAttribute("errorMessage", "");
			} else if (2 == processType) {
				// 현재 접속자
				request.setAttribute("errorMessage", "이미 접속자된 분이 있습니다. 로그인을 할 수 없습니다.");
			}
		}
	} else {
		request.setAttribute("errorMessage", "아이디/패스워드가 정확하지 않습니다.");
	}
}

로그인을 성공한 사용자 Id로 "TestSessionManager"에서 있는지 확인하고 없으면 추가합니다.

그러나 기존에 사용자 Id가 있으면 중복 로그인 방지 방식에 따라 기존 접속자를 로그아웃 시키고 현재 접속자를 로그인시키거나 기존 접속자의 로그인을 유지하고 현재 접속자를 차단할 수 있습니다.

 

 

중복 로그인 방지 테스트를 위해 첫 번째로 방식으로 테스트해보겠습니다.

3. "Servers"탭에서 "Tomcat8"를 선택하고 "start"버튼(start the server)을 클릭합니다. 웹 브라우저에서 "http://localhost:8080/test2/testform.do"를 입력합니다.

인증이 되지 않아서 "testform.jsp"대신 "login.jsp"가 호출되어 나타납니다.

 

"Console"탭을 클릭하면 확인할 수 있습니다.

 

첫 번째 입력란은 아이디, 두 번째 입력란은 패스워드입니다. 아이디는 "testid"를 패스워드는 "testpwd"를 입력하고 "전송"버튼을 누릅니다.

인증 처리되고 "testform.do"로 이동하게 됩니다.

"Console"탭을 클릭하면 확인할 수 있습니다.

사용자 세션이 "TestSessionManager"에 추가된 것을 확인할 수 있습니다.

테스트를 위해 IE 웹 브라우저에서 "http://localhost:8080/test2/testform.do"를 입력합니다.

 

아이디는 "testid"를 패스워드는 "testpwd"를 입력하고 "전송"버튼을 누릅니다.

인증 처리되고 "testform.do"로 이동하게 됩니다.

"Console"탭을 클릭하면 확인할 수 있습니다.

[Console]

HttpSession 파괴 실행 : javax.servlet.http.HttpSessionEvent[source=org.apache.catalina.session.StandardSessionFacade@2fbaa672]
Session Count : 1, Session ID : 957FCF32969826C99EAFDD67FDB44FF1
HttpSession에 속성 삭제 - 속성명 : auth, 속성 값 : com.home.project.test2.vo.UserVO@51a76514
Session Manager Count : 0, Remove ID : testid, Session ID : 957FCF32969826C99EAFDD67FDB44FF1
HttpSession에 속성 추가 - 속성명 : auth, 속성 값 : com.home.project.test2.vo.UserVO@218160eb
Session Manager Count : 1, Add ID : testid, Session ID : 674A0CF438E1B04E55B3F81B6F61F6ED

 

기존 접속자의 세션을 무효화(invalidate)되어 HttpSession이 파괴되고 "TestSessionManager"에서 제가 됩니다. 현재 접속자를 "TestSessionManager"에 추가됩니다.

크롬 웹 브라우저를 새로고침 합니다. 그러면 인증이 무효화되어 다시 로그인 페이지로 이동됩니다.

 

"Servers"탭에서 "Tomcat8"를 선택하고 "stop"버튼(stop the server)을 클릭합니다.

중복 로그인 방지 테스트를 위해 두 번째로 방식으로 테스트해보겠습니다.

4. "TestLoginService"의 "process"메서드에서 "processType"를 "1"에서 "2"로 변경하고 저장합니다.

 

"Servers"탭에서 "Tomcat8"를 선택하고 "start"버튼(start the server)을 클릭합니다. 이전과 동일하게 웹 브라우저에서 "http://localhost:8080/test2/testform.do"를 입력하고 아이디는 "testid"를 패스워드는 "testpwd"를 입력하고 "전송"버튼을 눌러 진행합니다.

인증 처리되고 "testform.do"로 이동하게 됩니다.

테스트를 위해 IE 웹 브라우저에서 "http://localhost:8080/test2/testform.do"를 입력하고 아이디는 "testid"를 패스워드는 "testpwd"를 입력하고 "전송"버튼을 누릅니다.

그러면 로그인 정보는 정상적이었지만 로그인을 하지 못한 것을 에러 메시지를 통해 확인할 수 있습니다.

"Console"탭을 클릭하면 확인할 수 있습니다.

 

"TestSessionManager"를 "processType"를 추가하고 수정한다면 중복 로그인을 허용하거나 로그인 허용 회수도 지정할 수 있게 처리할 수 있을 겁니다.

 

728x90
반응형