티스토리 뷰

1. 로그인 시도 횟수 제한


- 로그인 시도 횟수에 제약을 주지 않는다면 공격자는 툴을 이용하여 무작위 대입 공격을 시도해 사용자의 로그인 정보를 얻을 수 있다.


- 때문에 로그인 시도에 대한 횟수를 체크하여 계정에 대한 보호조치를 취하여 대입공격을 막아야 한다.


- Standalone 서버에서 Singleton Pattern 의 코드를 사용하면 편리하다.


2. Singleton Pattern ?


- 객체를 한번만 생성하고, 그 객체에 접근이 가능하도록 하는 기능


- 객체 생성할 때 실행되는 생성자는 private로 접근을 막는다.


- 기존의 방법으로 생성자를 매번 생성한다면 객체마다 값이 달라지지만 Singleton을 이용하면 값이 같아진다.




3. Singleton Pattern을 이용한 로그인 시도 횟수 제한


LoginStore라는 Class 생성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package kr.co.hucloud.security.code.example.common;
import java.util.HashMap;
import java.util.Map;
 
import javax.servlet.http.HttpSession;
 
public class LoginStore {
//    private static LoginStore loginStore = new LoginStore();
//    private static volatile LoginStore loginStore = new LoginStore();
    private static volatile LoginStore loginStore;
    
    private Map<String, HttpSession> loginSessions;
    
    private LoginStore() { //private 로 하면 생성자를 호출할 수 없다.
        loginSessions = new HashMap<String, HttpSession>();
    }
    
    // synchronized 동기화
    public static synchronized LoginStore getInstance() { // LoginStore 내부에서 생성자를 만든다.
        // static : (메모리를 따로 가져간다.) instance를 만들지 않아도 사용할 수 있다. 
//        LoginStore loginStore = new LoginStore();
        
        if (loginStore == null) {
            loginStore = new LoginStore();
        }
        return loginStore;
    }
    
    public void addString memberId, HttpSession session ) {
        loginSessions.put(memberId, session);
    }
    
    public HttpSession get( String memberId ) {
        return loginSessions.get(memberId);
    }
    
    public void logout( String memberId ) {
        if ( loginSessions.containsKey(memberId) ) {
            loginSessions.get(memberId).invalidate(); // logout 시키기
            loginSessions.remove(memberId);
        }
    }
    
}
 
cs




Controller 부분에서 로그인 횟수 제한에 대한 방어코드를 작성한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@RequestMapping(value=("/member/login"), method=RequestMethod.POST )
    public void login(LoginVO loginVO, HttpSession session, HttpServletResponse response) {
        
        if ( memberService.isAccountLock(loginVO.getId()) ) { //true라면 잠긴 상태
            SendMessage.send(response, "OVER");
            return;
        }
        
        boolean isLoginSuccess = memberService.login(session, loginVO);
        // 로그인 횟수 제한 방어코드 작성
        if ( isLoginSuccess ) {
            /*
             * 1. LOGIN_FAIL_COUNT를 0으로 초기화한다.
             * 2. IS_ACCOUNT_LOCK 를 'N'으로 초기화한다.
             * 3. LATEST_LOGIN_DATE를 현재시간으로 수정한다.
             */
            memberService.loginSuccess(loginVO.getId());
            
            // Token 값 생성 및 등록 코드 작성
            // 이후 게시판 글 쓰기 페이지에서 Token 값 전달 받아 비교.
            String csrfToken = UUID.randomUUID().toString();
            session.setAttribute(Session.CSRF_TOKEN, csrfToken);
        
        }
        else {
            /*
             * 1. LOGIN_FAIL_COUNT를 1 증가시킨다.
             */
            memberService.plusLoginFailCount(loginVO.getId());
            /*
             * 1. LOGIN_FAIL_COUNT가 5이상이라면 IS_ACCOUNT_LOCK를 'Y'로 수정한다.
             */
            memberService.updateAccountLock(loginVO.getId());
            /*
             * 1. IS_ACCOUNT_LOCK이 'Y'라면 브라우저에게 'OVER'라고 보낸다.
             *         OVER를 응답으로 받은 브라우저는 '로그인이 지속 실패하여 계정이 잠겼습니다. 운영자에게 문의하세요.'를 출력한다.
             */
            boolean isLock = memberService.isAccountLock(loginVO.getId());
            if( isLock ){
                SendMessage.send(response, "OVER");
                return;
            }
            
        }
        
        SendMessage.send(response, isLoginSuccess ? "OK" : "NO");
    }
cs



'Secure Coding' 카테고리의 다른 글

안전하지 않은 예외처리  (2) 2016.05.02
파일 업로드/다운로드 취약점  (0) 2016.05.02
크로스 사이트 요청 위조 [ CSRF ]  (0) 2016.04.29
크로스 사이트 스크립팅 [ XSS ]  (0) 2016.04.29
패스워드 정책  (0) 2016.04.28
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함