Programing/egovFramework

전자정부 JAVA 중복 로그인 방지 처리 방법, 동시접속 제한

리커니 2017. 12. 20.
반응형

 

전자정부 JAVA 중복 로그인 방지 처리 방법, 동시접속 제한

 

보안적인 측면에서 중복로그인 처리는 필수적으로 필요한 부분입니다.

내가 로그인 했는데 다른곳에서 또 로그인 처리가 되면 안되겠죠?

 

그럼 전자정부프레임워크를 활용해 중복로그인 방지 처리를 하는 방법을 알아보도록 하겠습니다.

포스팅은 아래의 Link를 참조하였습니다.

 

Link : 전자정부 프레임워크 중복 로그인 방지 기능

 

Link : Spring Interceptor 활용 세션 설정 인터셉터 세션 설정 ajax, 페이지연결 구분

 

인터셉터 설정 부분은 위의 링크를 참고하시고, 중복 로그인 처리부터 보도록 하겠습니다.

인터셉터 설정을 해 놓으면 페이지 요청이 있을 때마다 인터셉터가 가로채서

등록된 class 를 우선적으로 실행을 하게 되죠.

 

이번 포스팅에서 인터셉터는 중복로그인을 했을 때 세션이 어떻게 되는지 확인하는 용도로 사용하겠습니다.

 

우선, 전자정부 프레임워크에서는 중복 로그인 방지 기능을 위해 두개의 class를 제공하고 있는데요.

 

EgovHttpSessionBindingListener

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
 
public class EgovHttpSessionBindingListener implements HttpSessionBindingListener{
 
    @Override
    public void valueBound(HttpSessionBindingEvent event){
        if (EgovMultiLoginPreventor.findByLoginId(event.getName())){
            EgovMultiLoginPreventor.invalidateByLoginId(event.getName());
        }
        EgovMultiLoginPreventor.loginUsers.put(event.getName(), event.getSession());
    }
 
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        EgovMultiLoginPreventor.loginUsers.remove(event.getName(), event.getSession());
    }
}
cs

 

EgovMultiLoginPreventor 입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
 
import javax.servlet.http.HttpSession;
 
public class EgovMultiLoginPreventor {
    public static ConcurrentHashMap<String, HttpSession> loginUsers = new ConcurrentHashMap<String, HttpSession>();
 
    public static boolean findByLoginId(String loginId){
        return loginUsers.containsKey(loginId);
    }
 
    public static void invalidateByLoginId(String loginId){
        Enumeration<String> e = loginUsers.keys();
        while (e.hasMoreElements()){
            String key = (String) e.nextElement();
            if (key.equals(loginId)){
                loginUsers.get(key).invalidate();
            }
        }
    }
}
cs

 

간단한 로직입니다.

로그인을 할 때 로그인id와 세션id를 Map에 저장하고, 로그아웃할 때 제거하는 것이죠.

 

 

 

만약 1번 컴퓨터에서 test란 id로 로그인을 했다면 이 세션id와 로그인id가 Map에 저장됩니다.

그런데 2번 컴퓨터에서 test란 아이디로 로그인을 한다면,

기존에 같은 test란 id는 Map에서 제거되고, 새로운 값이 저장되는 것입니다.

그렇기 때문에 1번 컴퓨터에서는 강제 로그아웃 처리가 된 것이죠.

 

그럼 구현된 코드를 보도록 하죠.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RequestMapping(value="loginCheck.do", produces="text/plain;charset=UTF-8")
@ResponseBody
public String loginCheck(LoginVO param, HttpServletRequest request){
    Gson gson = new Gson();
    LoginSet set = new LoginSet();
    try {
        int memCnt = loginService.loginCheck(param);
        if(memCnt>0){
            request.getSession().setAttribute("TAATLoginId", param.getId());
            
            EgovHttpSessionBindingListener listener = new EgovHttpSessionBindingListener();
            request.getSession().setAttribute(param.getId(), listener);                
 
            set.setResultCode(Define.SUCCESS_CODE);
            set.setResultMsg(Define.SUCCESS_MSG);
        }else{
            set.setResultCode(Define.FAIL_CODE);
            set.setResultMsg(Define.LOGIN_FAIL_MSG);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return gson.toJson(set);
}
cs

 

ajax 요청으로 로그인에 대한 정보가 넘어옵니다.

7번째 라인에서 DB에 데이터가 있는지 확인을 하죠.

있다면(8번째 라인) 세션에 TAATLoginId로 파라메터로 넘어온 아이디를 저장하고,

EgovHttpSessionBindingListener 를 생성해 id와 함께 세션에 저장합니다.

이때 (12번째 라인) EgovHttpSessionBindingListener valueBound() 가 실행되며

id가 존재한다면 기존의 Map에서 제거하고, 없다면 저장 되는 것이죠.

 

하나의 id/sessionId 만이 Map에 존재하게 되는 것입니다.

그러니 인터셉터 쪽에서는 id를 확인할 수 없어 로그인 페이지로 이동되게 됩니다.

(인터셉터에 대해서는 위의 Link를 참고하세요.)

 

참고로 로그아웃 시에도 세션을 제거 해 주어야 겠죠?

 

1
2
3
4
5
6
@RequestMapping(value="/logout.do")
public String logout(HttpServletRequest request){
    RequestContextHolder.getRequestAttributes().removeAttribute("TAATLoginId", RequestAttributes.SCOPE_SESSION);
    request.getSession().invalidate();
    return "redirect:/loginPage.do";
}
cs

 

 

반응형

댓글

💲 추천 글