로그인 시도 횟수를 5회로 제한하고, 제한한 횟수를 초과 할 경우 10분간 로그인이 불가능 하도록 제어하는 코드를 추가 할 예정이다.
로그인 시도 횟수를 제한하는 이유는 다음과 같다!
(챗지피티가 알랴줌)
- 계정 보호: 제한된 로그인 시도 횟수는 악의적인 사용자가 무차별적으로 다양한 비밀번호를 시도하여 계정에 불법적으로 액세스하는 것을 방지합니다. 암호를 맞추기 위한 공격인 브루트 포스 공격(brute force attack)을 어렵게 만듭니다. 제한된 시도 횟수로 인해 일정 시간 동안 잠금 상태가 되거나, 추가적인 인증 단계가 필요한 경우, 악의적인 사용자의 로그인 시도가 제한됩니다.
- 암호 보호: 제한된 로그인 시도 횟수는 사용자가 취약한 암호를 사용하는 경우를 방지합니다. 악의적인 사용자가 계정에 접근하기 위해 다양한 암호 조합을 시도하는 경우, 제한된 시도 횟수로 인해 암호를 강력하게 유지하도록 유도됩니다. 강력한 암호는 알려진 패스워드 목록에 있는 비밀번호나 일반적인 패턴을 사용하는 것을 방지하고, 계정을 더 안전하게 보호할 수 있습니다.
- 계정 도용 방지: 제한된 로그인 시도 횟수는 계정 도용을 방지하는 데 도움을 줍니다. 비밀번호를 잊어버린 경우나 타인이 사용자의 계정에 접근한 것을 감지할 수 있습니다. 제한된 시도 횟수를 통해 일정 시간 동안 로그인을 시도하는 사용자에 대한 경고 또는 추가적인 인증 단계를 요구할 수 있습니다.
- 보안 감지 및 대응: 제한된 로그인 시도 횟수는 로그인 시도를 모니터링하고 악의적인 활동을 탐지하는 데 도움을 줍니다. 일정 횟수 이상의 실패한 로그인 시도는 보안 이벤트로 간주되고, 이를 기반으로 보안 대응 조치를 취할 수 있습니다. 예를 들어, 이상 로그인 시도를 감지하면 계정 잠금, 사용자에게 경고 알림 전송, 보안 팀에게 경고 등의 조치를 취할 수 있습니다.
길다...
간단히 말해서 로그인 시도 횟수에 제약을 주지 않는다면 해커 입장에서 무작위 공격(무차별 대입 공격)을 시도해 정보를 매우 쉽게 취득
가능하기 때문에 로그인 시도 횟수의 제한을 두어야 한다!
일단 로그인 기능이 구현되어 있고, USER의 정보를 담은 테이블이 있다는 가정하에 다음과 같은 컬럼을 추가 해 주면 된다.
LOGIN_FAIL_COUNT : 로그인 실패 횟수
LAST_LOGIN_FAIL_DATE : 마지막 로그인 실패 시간
그리고, 필요한 메서드는 다음과 같다.
selectLoginFailCount : 로그인 실패 정보를 select
updateLoginFailCount : 로그인 실패 정보를 UPDATE
clearLoginFailCount : 로그인 실패 정보를 clear
다음으로, 각 메서드의 동작 쿼리는 다음과 같다.
먼저, selectLoginFailCount
의 동작 쿼리이다.
SELECT
TO_CHAR(LAST_LOGIN_FAIL_TIME + (10/(24*60)), 'YYYY-MM-DD HH24:MI:SS')AS LOGIN_FAIL_TIME,
TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS CURRENT_TIME,
LOGIN_FAIL_COUNT
FROM 유저정보테이블
WHERE MEMBER_ID = '해당 멤버 아이디'
총 3개의 정보를 가져오는데
LOGIN_FAIL_TIME : 마지막 로그인 실패 시간 + 10분
CURRENT_TIME : 현재 시간
LOGIN_FAIL_COUNT : 로그인 실패 횟수
나는 로그인이 5회 이상 실패하면, 마지막 실패 시간으로부터 10분간 로그인을 제한 하기 위해 10분을 더해줬는데, 본인이 정하고 싶은 시간으로 변경해도 된다.
다음으로 updateLoginFailCount
의 동작 쿼리이다.
UPDATE 유저정보테이블
SET LOGIN_FAIL_COUNT = LOGIN_FAIL_COUNT + 1,
LAST_LOGIN_FAIL_TIME = SYSDATE
WHERE MEMBER_ID = '해당 멤버 아이디'
로그인이 실패 할 경우 LOGIN_FAIL_COUNT를 1씩 증가시켜주고, LAST_LOGIN_FAIL_TIME을 현재 시간으로 UPDATE 해 준다.
마지막으로 clearLoginFailCount
의 동작 쿼리이다.
UPDATE 유저정보테이블
SET LOGIN_FAIL_COUNT = 0
WHERE MEMBER_ID = '해당 멤버 아이디'
로그인 성공 혹은 로그인 제한 시간이 지났을 경우, LOGIN_FAIL_COUNT
를 초기화 해 준다.
이제, 로그인이 실패 했을 경우 소스코드를 본격적으로 구현 해 보자 !!! 나 같은 경우 cognito를 이용해 로그인이 구현 되어있기 때문에, 비밀번호를 잘못 입력 했을 경우 에러 코드는 NotAuthorizedException
이다.
따라서, 에러 코드가 NotAuthorizedException
인 경우에 로직을 추가 해 줬는데, 다른 에러코드를 넘겨받으면 그걸 넣어주면 된다. .
if (loginInfo.code == 'NotAuthorizedException') {
const params = {};
params.MEMBER_ID = reqQuery.loginId;
//selectLoginFailCount를 이용해 로그인 실패 정보를 가져옴
const loginFail = await common.selectLoginFailCount(params);
let LoginFailCount = loginFail.FAIL_DATA[0].LOGIN_FAIL_COUNT;
let LoginFailTime = loginFail.FAIL_DATA[0].LOGIN_FAIL_TIME;
let currentTime = loginFail.FAIL_DATA[0].CURRENT_TIME;
// 로그인 실패 카운트가 5회 이상일경우 제한
if (LoginFailCount > 4 ) {
//로그인 실패 횟수가 5회 이상인데, 10분이 지나지 않았을경우 메세지 출력
if ( LoginFailTime > currentTime ) {
loginResult.code = 'loginLock';
loginResult.message = '비밀번호 5회 불일치, 10분 뒤 재시도해주시기 바랍니다.';
}
//로그인 실패 횟수가 5회 이상인데, 10분이 지났을경우 기존 COUNT를 초기화 해 주고 새롭게 로그인 실패 횟수 카운트
else{
await common.clearLoginFailCount(params);
await common.updateLoginFailCount(params);
loginResult.code = 'E99';
loginResult.message = '로그인 실패!(비밀번호가 일치하지 않습니다.)';
}
}
//로그인 실패 카운트 횟수가 5회 미만일 경우 실패횟수 카운트
else{
await common.updateLoginFailCount(params);
loginResult.code = 'E99';
loginResult.message = '로그인 실패!(비밀번호가 일치하지 않습니다.)';
}
res.send(loginResult);
}
다음과 같이 코드를 구현해줬다. 로그인 실패 시마다 로그인 실패 정보를 확인하면서 제어를 해 준다.
로그인 실패 횟수가 5회 미만 : 로그인 실패 정보를 UPDATE
로그인 실패 횟수가 5회 이상이면서 제한시간이 남아있을경우 : error 코드와 message 출력
로그인 실패 횟수가 5회 이상이면서 제한시간이 남아있지않을경우 : 기존 로그인 실패 정보를 clear + 로그인 실패 정보를 UPDATE (어쨌든 또 실패한거니까!)
이렇게 구현 해 줬다. error 코드를 처리하는 부분까지 처리 해 주면 일단 로그인 실패 시 로직은 모두 구현된거다 ~
다음은 로그인을 성공했을 경우에도 코드를 추가해줘야한다.
if(로그인 성공 한 경우) {
const params = {};
params.MEMBER_ID = reqQuery.loginId;
const loginFail = await common.selectLoginFailCount(params);
let LoginFailCount = loginFail.FAIL_DATA[0].LOGIN_FAIL_COUNT;
let LoginFailTime = loginFail.FAIL_DATA[0].LOGIN_FAIL_TIME;
let currentTime = loginFail.FAIL_DATA[0].CURRENT_TIME;
if ( LoginFailCount > 4 && LoginFailTime > currentTime ) {
loginResult.code = 'loginLock';
loginResult.message = '비밀번호 5회 불일치, 10분 뒤 재시도해주시기 바랍니다.';
res.send(loginResult);
}else{
const params = {};
params.MEMBER_ID = reqQuery.loginId;
await common.clearLoginFailCount(params);
//로그인 성공 시 진행 로직 ..
}
}
사용자가 로그인 시도 제한을 넘은 상태에서, 로그인을 성공 했다고 해도 로그인이 제한되어있는 상태여야한다.
(10분동안은 아무런 시도도 불가능)
따라서, loginFailCount가 5회 이상이면서 남아있는 시간이 있을 경우, 로그인이 불가능하다는 error code와 message를 넘겨줘야한다.
loginFailCount가 5회 미만이거나 남아있는 시간이 없을 경우에는 로그인 실패 정보를 clear 해 주고 로그인 성공 시 진행되어야하는 로직을 입력해주면 된다 ~~~