본문 바로가기
Project/블로그 프로젝트

네이버 블로그 만들기 프로젝트(2) - 비밀번호 유효성검사 기능 구현

by 히앤님 2022. 10. 19.
반응형
SMALL

비밀번호 유효성검사 기능 구현

비밀번호는 간단하게 javascript에서 정규식으로 유효성 검사가 가능하다.

그럼에도 ajax 통신을 통해 뒷단에서 유효성 검사를 하는 이유1. 비밀번호 규칙 노출 방지 2. 소스보기로 노출되지 않도록 보안성을 위함이다.

따라서 id 중복검사와 같이 ajax로 컨트롤러 단에 보내 유효성검사 기능을 구현해보겠다.

네이버는 자물쇠 아이콘을 통해 비밀번호의 보안난이도를 표시한다. 사용불가 - 위험 - 보통 - 안전 - 빈 자물쇠 로 나뉘어져 있다.

1. 사용불가(red) - 8~16자 영문 대 소문자, 숫자, 특수문자를 사용하지 않는 경우
2. 위험(orenge) - 보안상 위험한 특정문구 및 숫자를 사용한 경우(1004, 8282, iloveyou, abc123)
3. 보통(brown) - 비밀번호 사용 가능. 영문자만, 숫자만 사용된 경우
4. 안전(green) - 영문자, 숫자, 특수문자 중 2개이상 섞어서 사용했을 경우

그 규칙성을 알 수 없으니, 임의로 규칙을 설정해서 만들어보았다.

[ 만들 기능 ]
1. 빈값 체크 & 연속된 숫자 제한
2. 유효성 검사(5~20자 특수문자 -와_만 허용)
3. 자물쇠 및 alert 변화
4. 비밀번호 확인란이 비밀번호와 값이 같도록 함

1. jsp에서 ajax 통신을 이용해서 호출 URL로 Data 보냄
2. Controller에서 호출 URL을 받아 Action과 연결함.
3. Action에서 getParameter로 가져온 userPwd값을 검사함.
4. 조건에 따라 결과값을 getWriter().write로 응답하는 스트림에 결과값 던져줌.
5. ajax 성공 결과값인 success로 와서 응답받은 result값에 따라 메시지 출력해줌.


1. 빈값체크 & 연속된 숫자 제한

연속된 숫자 및 기본 유효성검사 조건(8~16자 영문 대 소문자, 숫자, 특수문자를 사용)은 javascript 정규식 검사로 수행하면 편하다. 추가로 연속된 숫자도 제한하는 로직을 추가했다.

▼ joinUs.jsp - html 부분

<div class="join_row">
    <h3 class="join_title"><label for="pswd1">비밀번호</label></h3>
    <span class="ps_box int_pass" id="pswd1Img">
		<input type="password" id="pswd1" name="MEMBER_PW" class="int" title="비밀번호 입력" aria-describedby="pswd1Msg" maxlength="20">
        <span class="lbl"><span id="pswd1Span" class="step_txt"></span></span>
	</span>
    <span class="error_next_box" id="pswd1Msg" style="display:none" aria-live="assertive">5~12자의 영문 소문자, 숫자와 특수기호(_)만 사용 가능합니다.</span>

    <h3 class="join_title"><label for="pswd2">비밀번호 재확인</label></h3>
    <span class="ps_box int_pass_check" id="pswd2Img">
		<input type="password" id="pswd2" name="MEMBER_PW_cfm" class="int" title="비밀번호 재확인 입력" aria-describedby="pswd2Blind" maxlength="20">
		<span id="pswd2Blind" class="wa_blind">설정하려는 비밀번호가 맞는지 확인하기 위해 다시 입력 해주세요.</span>
	</span>
    <span class="error_next_box" id="pswd2Msg" style="display:none" aria-live="assertive"></span>
</div>

 joinUs.jsp - script 부분

//비밀번호1 체크 함수 시행 
   function checkPswd1() {
        if(pwFlag) return true;

        var id = $("#id").val();
        var pw = $("#pswd1").val();
        var oImg = $("#pswd1Img");
        var oSpan = $("#pswd1Span");
        var oMsg = $("#pswd1Msg");
        var oInput = $("#pswd1");

      	//============ [pwd1 필수입력] ============
        if (pw == "") { //공백제한
            showErrorMsg(oMsg,"필수 정보입니다.");
            setFocusToInputObject(oInput); //유효성 검증을 하고 전송 플래그를 조절한다.
            return false;
        }
      	
      	//============ [pwd1 기본 유효성검사] ============
        if (isValidPasswd(pw) != true) { //유효성검사
            showPasswd1ImgByStep(oImg, oSpan, 1); //비밀번호 괜찮은지 오른쪽 자물쇠 이미지
            showErrorMsg(oMsg,"8~16자 영문 대 소문자, 숫자, 특수문자를 사용하세요.");
            setFocusToInputObject(oInput); //유효성 검증을 하고 전송 플래그를 조절한다.
            return false;
        }else if(checkpswd1_sameNum(pw) == true){ //비밀번호 연속동일숫자가 맞으면
        	showPasswd1ImgByStep(oImg, oSpan, 2); //비밀번호 괜찮은지 오른쪽 자물쇠 이미지
            showErrorMsg(oMsg,"보안상 연속된 숫자는 제한합니다.");
            setFocusToInputObject(oInput); //유효성 검증을 하고 전송 플래그를 조절한다.
            return false;
        }

        ... 
        
        // 이곳에 ajax 통신 예정
        
        ...
		return true;
   } //function checkPswd1() { 끝

기본 유효성 검사를 진행하는 isValidPasswd() 함수는 다음과 같다.

  	//============ [pwd1 패스워드 검증] ============
    function isValidPasswd(str) {
    	console.log("입력한 Pwd값 검증1 : " + str);
        if (str == "") {
            return false;
        }

        // 공백 걸러내기
        var retVal = checkSpace(str);
        if (retVal) {
            return false;
        }
        
     	// 8자리 미만 불가
        if (str.length < 8) {
            return false;
        }
     	
        //8~12자의 영문 소문자, 숫자, 특수문자만 사용 가능
        var isPW = /^[A-Za-z0-9`\-=\\\[\];',\./~!@#\$%\^&\*\(\)_\+|\{\}:"<>\?]{8,16}$/;
        if (!isPW.test(str)) {
            return false;
        }

        return true;
    }

연속된 숫자 불가하게 하는 checkpswd1_sameNum()함수는 다음과 같다.

//  연속된 숫자 불가
  	function checkpswd1_sameNum(str){
  		
	
    	var cnt = 0;
  		 //연속된 숫자 불가
        for (var i = 0; i < str.length; ++i) {
            if (str.charAt(0) == str.substring(i, i + 1))
                ++cnt;
        }
        if (cnt == str.length) {
        	console.log("연속된 숫자");
        	console.log("입력한 Pwd값 검증2 : " + str);
           return true;
        }
    }

2. ajax 통신을 통해 비밀번호 검증

ajax 통신을 통해 비밀번호 검증을 한다. DB 연결없이 컨트롤러 단에서 해결해보자.

 joinUs.jsp - script 부분

//비밀번호1 체크 함수 시행 
   function checkPswd1() {
   
   ...
   
    // 추가) ajax 통신으로 컨트롤러단에서 비밀번호 유효성검사하기!(post 방식) 
        pwFlag = false; //검사 flag
        let userPwd = $('input[name=MEMBER_PW]').val(); // input_id에 입력되는 값
        console.log("입력한 Pwd값 : " + userPwd);

        $.ajax({
            url: "PwdCheckService/pwdcheckAjax",
            type: "post",
            data: {
            	userPwd: userPwd 
            },
            dataType: 'json',
            success: function (result) {
            //===========================================
            	//왜 굳이 컨트롤러로 보내나? 이유는 보안상의 이유.
            	// 백단에서 1004 이런거 안되게 한다던지 등 비밀번호 검증 쿼리가 있을듯.
            	//https://lky1.tistory.com/17 정규식 참고함
                if (result == 1) { //사용불가
                    showPasswd1ImgByStep(oImg, oSpan, 1); //비밀번호 괜찮은지 오른쪽 자물쇠 이미지
                    showErrorMsg(oMsg,"8~16자 영문 대 소문자, 숫자, 특수문자를 사용하세요.");
                    setFocusToInputObject(oInput);//유효성 검증을 하고 전송 플래그를 조절한다.
                    return false;
                } else if (result == 2) { //위험
                    showPasswd1ImgByStep(oImg, oSpan, 2);//비밀번호 괜찮은지 오른쪽 자물쇠 이미지
                    showErrorMsg(oMsg,"보안상 특정문구 및 숫자는 사용불가합니다.(1004, 8282, iloveyou, abc123 등)");
                    setFocusToInputObject(oInput);
                } else if (result == 3) { //보통
                    showPasswd1ImgByStep(oImg, oSpan, 3);//비밀번호 괜찮은지 오른쪽 자물쇠 이미지
                    showErrorMsg(oMsg,"영문자, 숫자, 특수문자 2가지 이상 섞어서 사용하세요.");
                    setFocusToInputObject(oInput);
                } else if (result == 4) { //안전
                    showPasswd1ImgByStep(oImg, oSpan, 4);//비밀번호 괜찮은지 오른쪽 자물쇠 이미지
                    oMsg.hide();
                } else { //빈 자물쇠
                    showPasswd1ImgByStep(oImg, oSpan, 0);//비밀번호 괜찮은지 오른쪽 자물쇠 이미지
                    oMsg.hide();
                }
                pwFlag = true; //비밀번호 플래그 1로 바꿔준다.
                        
            //===========================================
            }, 
            error: function () {
                alert("서버요청실패");
            }
        })
        
        return true;
        
    } //function checkPswd1() { 끝

3.  Controller

비밀번호 유효성 검사를 할 Action 페이지로 연결해준다.

  MemberFrontController.java

//-------------------- 비밀번호를 검증하는 MemberPwdCheckAction 페이지 생성 ---------------------------				
else if (command.equals("/member/PwdCheckService/pwdcheckAjax")) {
    action = new MemberPwdCheckAction();
    //규칙은 보기 쉽게 자물쇠 아이콘에 tip을 달자!
    try {

        forward = action.execute(req, resp); //???
        System.out.printf( "MemberFrontController : pwdCheck 성공",req, resp))

    }
    catch (Exception e) {
        e.printStackTrace();
        System.out.println( "MemberFrontController : pwdCheck 실패"))
    }
}

4.  Action

조건에 따라 특정 문구 금지하고, 여러 유형의 비밀번호가 허용될 수 있도록 result 값을 설정해준다.

  MemberPwdCheckAction.java

package action;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import vo.ActionForward;

/* 인터페이스를 함께 추가했다. id 중복체크 처리를 위한 클래스이다.*/
public class MemberPwdCheckAction implements Action { // Action을 implements 해줌

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		// =========================== pwd 조건 처리 ================================
		String userPwd = req.getParameter("userPwd"); // ajax로 전달한 data 값 userPwd
		System.out.println("Action 내부) 입력한 pwd : " + userPwd);
	
		PrintWriter out = resp.getWriter();
		String result = ""; //결과값 담을 변수

		// 1. 위험 : 1004, 8282, iloveyou, abc123 포함하면 안됨
		if (userPwd.contains("1004") || userPwd.contains("8282") || userPwd.contains("iloveyou") || userPwd.contains("abc123")) { 
			System.out.println("위험- 1004, 8282, iloveyou, abc123 포함하면 안됨");
			result = "2";
            
		// 2. 보통 : 영문자만, 숫자만 있을 때
		} else if (userPwd.matches("^[a-zA-Z]*$") || userPwd.matches("^[0-9]*$") ) {
			//* : 0회 이상(여러개) = 여러개의 문자가 모두 영문자 of 모두 숫자일 때
			System.out.println("보통 - 영문자만, 숫자만 있을 때");
			result = "3";
            
		// 2. 안전 : 그 이외(영문+특수문자, 숫자+특수문자, 영문+숫자, 영문+숫자+특수문자)
		} else {
			System.out.println("안전 = 영문자, 숫자, 특수문자 중 2개이상 섞어썼을 때");
			result = "4";
		} 

		out.write(result); // 얘는 마지막에만 선언해줘야함. if문이나 else 등에서 여러번 못쓴다.
		// --> ajax 결과값인 result가 됨
		// ajax의 result값 : 문자로 보내도 숫자로 감.
		return null;
		// ActionForward를 null로 리턴하면 이미 response에 응답을 끝냈다는 의미가 된다. 다른 어떤 페이지로도 이동하지 않는다.
	}
}

5. 자물쇠 이미지 및 글씨 설정

자물쇠 아래 글씨 색상으로 표시해주자.

  joinUs.jsp - script 부분

//============ [비밀번호 괜찮은지 오른쪽 자물쇠 이미지] ============
   function showPasswd1ImgByStep(oImg, oSpan, step) {
       if("IE8" == "") {
           return false;
       }
       if(step == 1) {
           oImg.attr("class", "ps_box int_pass_step1");
           oSpan.attr("class", "step_txt txt_red");
           oSpan.html("사용불가");
       } else if(step == 2) {
           oImg.attr("class", "ps_box int_pass_step2");
           oSpan.attr("class", "step_txt txt_orange");
           oSpan.html("위험");
       } else if(step == 3) {
           oImg.attr("class", "ps_box int_pass_step3");
           oSpan.attr("class", "step_txt txt_yellow");
           oSpan.html("보통");
       } else if(step == 4) {
           oImg.attr("class", "ps_box int_pass_step4");
           oSpan.attr("class", "step_txt txt_green");
           oSpan.html("안전");
       } else {
           oImg.attr("class", "ps_box int_pass");
           oSpan.attr("class", "step_txt");
           oSpan.html("");
       }
   }

6. 비밀번호 확인

비밀번호 확인은 자물쇠 말고 errorMsg로만 표시되게 하였다.

  joinUs.jsp - script 부분

 	//============ [비밀번호2 체크 함수 시행 -> 자물쇠 말고 아래 글씨로만 표현] ============
    function checkPswd2() {
        var pswd1 = $("#pswd1");
        var pswd2 = $("#pswd2");
        var oMsg = $("#pswd2Msg");
        var oImg = $("#pswd2Img");
        var oBlind = $("#pswd2Blind");
        var oInput = $("#pswd2");

        if (pswd2.val() == "") {
     
            showErrorMsg(oMsg,"필수 정보입니다.");
            oBlind.html("설정하려는 비밀번호가 맞는지 확인하기 위해 다시 입력 해주세요.");
            setFocusToInputObject(oInput);
            return false;
        }
        if (pswd1.val() != pswd2.val()) {
            showErrorMsg(oMsg,"비밀번호가 일치하지 않습니다.");
            setFocusToInputObject(oInput);
            return false;
        } else {
            showSuccessMsg(oMsg,"일치합니다");
            oBlind.html("일치합니다");
            
            //2초뒤 천천히 사라지게 하기
            setTimeout(() => hideMsg(oMsg), 2000);
            
            return true;
        }
        return true;
    }

7. 키보드 제한(pwd1,2 둘다)

shift키 사용 또는 capslock을 판단한다. caps Lock의 경우 메시지를 표시해 눌려져 있다는 것을 사용자에게 알린다.

추가로 스페이스 제거도 해준다.

  joinUs.jsp - script 부분

/*=================================================
					키보드 관련 이벤트들
=================================================*/    
     
    //region 공통 함수
    function getLenChar(texts) {
        texts = texts + '';
        return String.fromCharCode(texts.length);
    }



    function checkSpace(str) { //스페이스 제거
        if (str.search(/\s/) != -1) {
            return true;
        } else {
            return false;
        }
    }
  	//============ [pwd1,2 패스워드 키보드 제한] ============	
    var isShift = false;
    function checkShiftUp(e) {
        if (e.which && e.which == 16) {
            isShift = false;
        }
    }

    function checkShiftDown(e) {
        if (e.which && e.which == 16) {
            isShift = true;
        }
    }

    function checkCapslock(e) {
        var myKeyCode = 0;
        var myShiftKey = false;
        if (window.event) { // IE
            myKeyCode = e.keyCode;
            myShiftKey = e.shiftKey;
        } else if (e.which) { // netscape ff opera
            myKeyCode = e.which;
            myShiftKey = isShift;
        }

        var oMsg = $("#pswd1Msg");
        if ((myKeyCode >= 65 && myKeyCode <= 90) && !myShiftKey) {
            showErrorMsg(oMsg,"Caps Lock이 켜져 있습니다.");
        } else if ((myKeyCode >= 97 && myKeyCode <= 122) && myShiftKey) {
            showErrorMsg(oMsg,"Caps Lock이 켜져 있습니다.");
        } else {
            hideMsg(oMsg);
        }
    }

    function checkCapslock2(e) {
        var myKeyCode = 0;
        var myShiftKey = false;
        if (window.event) { // IE
            myKeyCode = e.keyCode;
            myShiftKey = e.shiftKey;
        } else if (e.which) { // netscape ff opera
            myKeyCode = e.which;
            myShiftKey = isShift;
        }

        var oMsg = $("#pswd2Msg");
        if ((myKeyCode >= 65 && myKeyCode <= 90) && !myShiftKey) {
            showErrorMsg(oMsg,"Caps Lock이 켜져 있습니다.");
        } else if ((myKeyCode >= 97 && myKeyCode <= 122) && myShiftKey) {
            showErrorMsg(oMsg,"Caps Lock이 켜져 있습니다.");
        } else {
            hideMsg(oMsg);
        }
    }//============ [pwd1,2 패스워드 키보드 제한 끝] ============

 

빈값체크(빈자물쇠) / 8자 이상(사용불가) / 연속된숫자 제한(위험)
특정문구 제한(위험) / 숫자만, 영문만(보통) / 2가지이상(안전)

오류는 댓글 부탁드립니다.

▼ 진행중인 gitHub 링크를 남깁니다.

 

GitHub - k-haein/BlogPrj: 회원가입/로그인/게시글 등록 등의 블로그를 처음부터 만듭니다.

회원가입/로그인/게시글 등록 등의 블로그를 처음부터 만듭니다. Contribute to k-haein/BlogPrj development by creating an account on GitHub.

github.com

 

반응형
LIST

댓글