본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Spring framework

Spring HttpSessionListener를 활용한 세션 중복값 체크(중복 로그인 방지, 전자정부 중복 로그인)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2020. 4. 13.

스프링 시큐리티를 사용하지 않고 단순히 세션값을 활용하여 중복 로그인을 방지하는 방법에 HttpSessionListener 인터페이스가 사용이 된다.

해당 인터페이스를 implements하면 세션이 생성되고 소멸되는 시점에 대해서 작업을 용이하게 할 수 있다.

HttpSessionListener 인터페이스를 상속받아보면, 2개의 메소드가 오버라이딩 된다.

생성용 Created메소드, 소멸용 Destroyed 메소드

 

그러면 머리를 조금만써서..

특정 기능에서 로그인 성공시 세션을 만들어주고나면 해당 세션을 특정값에 보관하고,

로그아웃이나 중복로그인 발생시 저장된 세션값을 제거해주도록 하면 될 것 같다.

 

첫번째로 위 HttpSessionListener인터페이스를 상속받자.

그리고 로그인 성공에 대해서 정보를 공유할 컬렉션 객체를 만들어주자.

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;


@WebListener
public class SessionConfig implements HttpSessionListener{
	
    private static final Map<String, HttpSession> sessions = new ConcurrentHashMap<>();

    @Override
    public void sessionCreated(HttpSessionEvent hse) {
        System.out.println(hse);
        sessions.put(hse.getSession().getId(), hse.getSession());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent hse) {
        if(sessions.get(hse.getSession().getId()) != null){
            sessions.get(hse.getSession().getId()).invalidate();
            sessions.remove(hse.getSession().getId());	
        }
    }
}

 

sessions라는 Map을 만들어서 키값으로 세션의 고유 생성 아이디값, 값으로는 HttpSession을 갖도록 하였다.

로그인 성공시 새션이 만들어지게 되면 에노테이션 WebListener에 의해서 세션값이 sessions에 저장이 되고,

로그아웃이나 브라우저를 종료하여 세션이 사라지게되면 Destroyed에 의해서 제거되게 하였다.

 

여기까지는 사용자의 로그인, 로그아웃에 대한 처리이며, 만약 중복로그인을 하게 될 경우에는 추가적인 작업을 해야 된다.

로그인을 담당하는 곳 에서 해당 정보가 올바른 경우 이미 로그인한 세션값을 제거하도록 메소드를 추가하여 보자.

//..임포트 생략

@WebListener
public class SessionConfig implements HttpSessionListener{
	
    private static final Map<String, HttpSession> sessions = new ConcurrentHashMap<>();

    //중복로그인 지우기
    public synchronized static String getSessionidCheck(String type,String compareId){
        String result = "";
        for( String key : sessions.keySet() ){
            HttpSession value = sessions.get(key);
            if(value != null &&  value.getAttribute(type) != null && value.getAttribute(type).toString().equals(compareId) ){
                //System.out.println(value.getAttribute(type).toString());
                result =  key.toString();
            }
        }
        removeSessionForDoubleLogin(result);
        return result;
    }
    
    private static void removeSessionForDoubleLogin(String userId){    	
        System.out.println("remove userId : " + userId);
        if(userId != null && userId.length() > 0){
            sessions.get(userId).invalidate();
            sessions.remove(userId);    		
        }
    }

    @Override
    public void sessionCreated(HttpSessionEvent hse) {
        System.out.println(hse);
        sessions.put(hse.getSession().getId(), hse.getSession());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent hse) {
        if(sessions.get(hse.getSession().getId()) != null){
            sessions.get(hse.getSession().getId()).invalidate();
            sessions.remove(hse.getSession().getId());	
        }
    }
}    

 

getSessionidCheck 메소드를 통해서 세션의 값과 비교할 로그인 아이디값을 받도록 만들어 보았다.

synchronidez를 통해서 순차적인 처리를 하도록 하였다.

세션에 저장한 id값이 키가 user_id 면서 값이 admin일 경우 아래처럼 호출하여 세션에서 중복된 아이디를 검사 후 제거하게 하면 된다.

아래 간단한 컨트롤러를 통한 예를 만들어 보았다.

@Controller
public class LoginController {

    @Resource(name = "loginService")
    private LoginService loginSerivce;

    @RequestMapping(value = "/login")
    public String login (@RequestParam  HashMap<Object, Object> param, HttpSession session){
        HashMap<Object, Object> vo = loginSerivce.selectLogin(param);
        String userId = SessionConfig.getSessionidCheck("user_id", vo.get("user_id").toString());
        session.setMaxInactiveInterval(60*60);
        session.setAttribute("user_id", vo.get("user_id").toString());
        return "dashboard";
    }
}

 

간단하게 꾸며본 로그인 컨트롤러이다.

getSessionidCheck이라는 메소드를 호출하여 2중로그인 방지를 하였다.

이런식으로 로그인 성공시에 세션값을 확인하여 제거를 하게 된 다면 여러 곳에서 로그인 되는 행위를 막을 수 있다.

 

WebListener 에노테이션을 사용하지 않고 web.xml에서 등록하여 사용한다면 listener 테그를 사용하여 추가하여주면 된다.

	<listener>
		<listener-class>패키지명.SessionConfig</listener-class>
	</listener>

 

이상으로 스프링(전자정부 프레임워크)에서 세션값을 공유하여 중복 로그인을 방지하는 방법에 대해서 살펴 보았다.

해당 세션값에 ip나, 브라우저같은 정보를 활용하면 조금 더 다양한 중복 로그인 방지법을 만들어 볼 수 있다.

 

* 스프링에서의 세션(session)은 웹 브라우저가 해당 서버에 접속하면 바로 생성이 된다.

* 생성의 시기가 로그인이 아니라, 웹 브라우저의 접속으로부터 이므로 로그인시 세션값을 추가하는 행위는 update나 set의 개념으로 생각 해야 한다.

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글