Spring

[Spring ] 회원관리_인증처리_ 22.08.03 [15일차]

양빵빵 2022. 8. 3. 16:59

1. 회원가입

   * 입력값 검증 [아이디 이메일 중복여부]

 

2. 로그인 / 자동로그인

  * 로그인을 유지하기 위한 수단 = 세션

 

3. 인증처리 /  인가처리

    ex) 코스트코 회원권을 들고 있다 = 인증

    ex) VIP구역에 들어갈수 있는지 여부 = 인가

 === 실무에서 spring security 를 사용하지만 강의 시간에는 최대한 security를 쓰지 않고 만들어 보도록 한다. 

 

※ 회원 수정/탈퇴는 각자 알아서[강의에서는 다루지 않는다.]

 

 

== 패스워드 암호화 빌드설정

 

=BCryptPasswordEncoder();

 

 

 

 

== 중복체크 기능 마이바티스 xml

 

 

 

 

 

== 중복확인 중간처리 service 메서드

 

 

== 회원관리 MemberController

 

 

 

 

 

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="ko">
<head>
    <%@ include file="../include/static-head.jsp" %>
</head>
<body>



    <%@ include file="../include/header.jsp" %>
    <div class="container">
        <div class="row">
            <div class="offset-md-2 col-md-4">
                <div class="card" style="width:200%;">
                    <div class="card-header text-white" style="background: #343A40;">
                        <h2><span style="color: gray;">MVC</span> 회원 가입</h2>
                    </div>
                    <div class="card-body">
    
    
                        <form action="/member/sign-up" name="signup" id="signUpForm" method="post" style="margin-bottom: 0;">
    
    
                            <table style="cellpadding: 0; cellspacing: 0; margin: 0 auto; width: 100%">
                                <tr>
                                    <td style="text-align: left">
                                        <p><strong>아이디를 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;
                                            <span id="idChk"></span></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td><input type="text" name="account" id="user_id" class="form-control tooltipstered"
                                            maxlength="14" required="required" aria-required="true"
                                            style="margin-bottom: 25px; width: 100%; height: 40px; border: 1px solid #d9d9de"
                                            placeholder="숫자와 영어로 4-14자">
                                    </td>
    
                                </tr>
    
                                <tr>
                                    <td style="text-align: left">
                                        <p><strong>비밀번호를 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;<span id="pwChk"></span></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td><input type="password" size="17" maxlength="20" id="password" name="password"
                                            class="form-control tooltipstered" maxlength="20" required="required"
                                            aria-required="true"
                                            style="ime-mode: inactive; margin-bottom: 25px; height: 40px; border: 1px solid #d9d9de"
                                            placeholder="영문과 특수문자를 포함한 최소 8자"></td>
                                </tr>
                                <tr>
                                    <td style="text-align: left">
                                        <p><strong>비밀번호를 재확인해주세요.</strong>&nbsp;&nbsp;&nbsp;<span id="pwChk2"></span></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td><input type="password" size="17" maxlength="20" id="password_check" name="pw_check"
                                            class="form-control tooltipstered" maxlength="20" required="required"
                                            aria-required="true"
                                            style="ime-mode: inactive; margin-bottom: 25px; height: 40px; border: 1px solid #d9d9de"
                                            placeholder="비밀번호가 일치해야합니다."></td>
                                </tr>
    
                                <tr>
                                    <td style="text-align: left">
                                        <p><strong>이름을 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;<span id="nameChk"></span></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td><input type="text" name="name" id="user_name" class="form-control tooltipstered"
                                            maxlength="6" required="required" aria-required="true"
                                            style="margin-bottom: 25px; width: 100%; height: 40px; border: 1px solid #d9d9de"
                                            placeholder="한글로 최대 6자"></td>
                                </tr>
    
    
                                <tr>
                                    <td style="text-align: left">
                                        <p><strong>이메일을 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;<span id="emailChk"></span></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td><input type="email" name="email" id="user_email" class="form-control tooltipstered"
                                            required="required" aria-required="true"
                                            style="margin-bottom: 25px; width: 100%; height: 40px; border: 1px solid #d9d9de"
                                            placeholder="ex) abc@mvc.com"></td>
                                </tr>
    
    
                                <tr>
                                    <td style="padding-top: 10px; text-align: center">
                                        <p><strong>회원가입하셔서 더 많은 서비스를 사용하세요~~!</strong></p>
                                    </td>
                                </tr>
                                <tr>
                                    <td style="width: 100%; text-align: center; colspan: 2;">
                                        <input type="button" value="회원가입" class="btn form-control tooltipstered"
                                            id="signup-btn"
                                            style="background: gray; margin-top: 0; height: 40px; color: white; border: 0px solid #388E3C; opacity: 0.8">
                                    </td>
                                </tr>
    
                            </table>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>



    <%@ include file="../include/footer.jsp" %>
</body>
</html>

 

spring security 기본 로그인 폼

 

== void처리 =>  메서드의 요청 url과 리턴 url이 같을 경우

 

 

 

== spring security 기본 설정 끄기

 

 

 

 

 

 

 

 

== jQuery 아이디, 이름, 패스워드, 이름 검증식

 

 

 

 

 

 

 

 

 

 

 

 

 

 

# fetch API: 자바스크립트에서 제공하는 비동기 통신 함수
            - Promise를 자동 리턴하여 손쉽게 통신의 응답데이터를
              소비할 수 있게 해줌.
            - fetch함수가 리턴하는 Promise는 단순한 응답 JSON데이터가 아닌
              전체적이고 포괄적인 응답 정보를 가지고 있습니다.
            - 따라서 서버가 응답한 여러 정보 중 JSON데이터만  소비하려면
              json()이라는 메서드를 사용합니다.
              문자열 데이터라면 text()메서드를 사용합니다.

// 검증 스크립트 포함 jsp 풀버전

 

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
        <!DOCTYPE html>
        <html lang="ko">

        <head>
            <%@ include file="../include/static-head.jsp" %>

                <style>
                    .container {
                        margin: 200px auto 200px;
                    }

                    .c-red {
                        color: red;
                    }

                    .c-blue {
                        color: blue;
                    }
                </style>
        </head>

        <body>



            <%@ include file="../include/header.jsp" %>
                <div class="container">
                    <div class="row">
                        <div class="offset-md-2 col-md-4">
                            <div class="card" style="width:200%;">
                                <div class="card-header text-white" style="background: #343A40;">
                                    <h2><span style="color: gray;">MVC</span> 회원 가입</h2>
                                </div>
                                <div class="card-body">


                                    <form action="/member/sign-up" name="signup" id="signUpForm" method="post"
                                        style="margin-bottom: 0;">


                                        <table style="cellpadding: 0; cellspacing: 0; margin: 0 auto; width: 100%">
                                            <tr>
                                                <td style="text-align: left">
                                                    <p><strong>아이디를 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;
                                                        <span id="idChk"></span>
                                                    </p>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td><input type="text" name="account" id="user_id"
                                                        class="form-control tooltipstered" maxlength="14"
                                                        required="required" aria-required="true"
                                                        style="margin-bottom: 25px; width: 100%; height: 40px; border: 1px solid #d9d9de"
                                                        placeholder="숫자와 영어로 4-14자">
                                                </td>

                                            </tr>

                                            <tr>
                                                <td style="text-align: left">
                                                    <p><strong>비밀번호를 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;<span
                                                            id="pwChk"></span></p>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td><input type="password" size="17" maxlength="20" id="password"
                                                        name="password" class="form-control tooltipstered"
                                                        maxlength="20" required="required" aria-required="true"
                                                        style="ime-mode: inactive; margin-bottom: 25px; height: 40px; border: 1px solid #d9d9de"
                                                        placeholder="영문과 특수문자를 포함한 최소 8자"></td>
                                            </tr>
                                            <tr>
                                                <td style="text-align: left">
                                                    <p><strong>비밀번호를 재확인해주세요.</strong>&nbsp;&nbsp;&nbsp;<span
                                                            id="pwChk2"></span></p>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td><input type="password" size="17" maxlength="20" id="password_check"
                                                        name="pw_check" class="form-control tooltipstered"
                                                        maxlength="20" required="required" aria-required="true"
                                                        style="ime-mode: inactive; margin-bottom: 25px; height: 40px; border: 1px solid #d9d9de"
                                                        placeholder="비밀번호가 일치해야합니다."></td>
                                            </tr>

                                            <tr>
                                                <td style="text-align: left">
                                                    <p><strong>이름을 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;<span
                                                            id="nameChk"></span></p>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td><input type="text" name="name" id="user_name"
                                                        class="form-control tooltipstered" maxlength="6"
                                                        required="required" aria-required="true"
                                                        style="margin-bottom: 25px; width: 100%; height: 40px; border: 1px solid #d9d9de"
                                                        placeholder="한글로 최대 6자"></td>
                                            </tr>


                                            <tr>
                                                <td style="text-align: left">
                                                    <p><strong>이메일을 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;<span
                                                            id="emailChk"></span></p>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td><input type="email" name="email" id="user_email"
                                                        class="form-control tooltipstered" required="required"
                                                        aria-required="true"
                                                        style="margin-bottom: 25px; width: 100%; height: 40px; border: 1px solid #d9d9de"
                                                        placeholder="ex) abc@mvc.com"></td>
                                            </tr>


                                            <tr>
                                                <td style="padding-top: 10px; text-align: center">
                                                    <p><strong>회원가입하셔서 더 많은 서비스를 사용하세요~~!</strong></p>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td style="width: 100%; text-align: center; colspan: 2;">
                                                    <input type="button" value="회원가입"
                                                        class="btn form-control tooltipstered" id="signup-btn"
                                                        style="background: gray; margin-top: 0; height: 40px; color: white; border: 0px solid #388E3C; opacity: 0.8">
                                                </td>
                                            </tr>

                                        </table>
                                    </form>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <script>
                    //회원가입 폼 검증 - jquery
                    $(document).ready(function () {
                        //입력값 검증 정규표현식
                        const getIdCheck = RegExp(/^[a-zA-Z0-9]{4,14}$/); // ^ : ~로 시작하는 $ : 끝나는 {4~14} : 최소~최대
                        const getPwCheck = RegExp(
                            // 영문 숫자과 들어가야하고 특수기호를 하나라도 포함해야 하고 또는 시작을 특수문자로 해도 되고
                            // 영문과 숫자가 들어가야한다.
                            /([a-zA-Z0-9].*[!,@,#,$,%,^,&,*,?,_,~])|([!,@,#,$,%,^,&,*,?,_,~].*[a-zA-Z0-9])/);
                        const getName = RegExp(/^[가-힣]+$/); // 한글로 써야 한다. 유니코드 시작과 끝 가 - 힣
                        const getMail = RegExp(/^[A-Za-z0-9_\.\-]+@[A-Za-z0-9\-]+\.[A-Za-z0-9\-]+/);
                        // 영어로 시작하고 + 골뱅이 + 영문 + . + 영문

                        // 입력값 검증 배열
                        //1.아이디, 2.비번, 3.비번확인, 4.이름 , 5.이메일
                        const checkArr = [false, false, false, false, false];

                        //1. 아이디 검증
                        const $idInput = $('#user_id');
                        $idInput.on('keyup', e => {
                            // 아이디를 입력하지 않은 경우
                            if ($idInput.val().trim() === '') {
                                $idInput.css('border-color', 'red');
                                $('#idChk').html('<b class = "c-red">[아이디는 필수 정보 입니다.]</b>')
                                checkArr[0] = false;
                            }

                            // 아이디를 패턴에 맞지 않게 입력 하였을 경우
                            // test() 메서드는 정규표현식을 검증하여 입력값이 표현식과
                            // 일치하면 true, 일치하지 않으면 false를 리턴
                            else if (!getIdCheck.test($idInput.val())) {
                                $idInput.css('border-color', 'red');
                                $('#idChk').html('<b class = "c-red">[영문,숫자로 4~14자 사이로 작성하세요!]</b>')
                                checkArr[0] = false;
                            }

                            // 아이디 중복 확인 검증
                            else {

                                fetch('/member/check?type=account&value=' + $idInput.val())
                                    .then(res => res.text())
                                    .then(flag => {
                                        console.log('flag:', flag);

                                        if (flag === 'true') {
                                            $idInput.css('border-color', 'red');
                                            $('#idChk').html('<b class = "c-red">[중복된 아이디 입니다.]</b>')
                                            checkArr[0] = false;

                                        } // 정상적으로 입력한 경우
                                        else {
                                            $idInput.css('border-color', 'skyblue');
                                            $('#idChk').html('<b class = "c-blue">[허용 가능한 아이디 입니다.]</b>')
                                            checkArr[0] = true;
                                        }
                                    });

                            }

                        }); //end id check event

                        //패스워드 입력값 검증.
                        $('#password').on('keyup', function () {
                            //비밀번호 공백 확인
                            if ($("#password").val() === "") {
                                $('#password').css('border-color', 'red');
                                $('#pwChk').html('<b class="c-red">[패스워드는 필수정보!]</b>');
                                checkArr[1] = false;
                            }
                            //비밀번호 유효성검사
                            else if (!getPwCheck.test($("#password").val()) || $("#password").val().length < 8) {
                                $('#password').css('border-color', 'red');
                                $('#pwChk').html('<b class="c-red">[특수문자 포함 8자이상]</b>');
                                checkArr[1] = false;
                            } else {
                                $('#password').css('border-color', 'skyblue');
                                $('#pwChk').html('<b class="c-blue">[참 잘했어요]</b>');
                                checkArr[1] = true;
                            }

                        });

                        //패스워드 확인란 입력값 검증.
                        $('#password_check').on('keyup', function () {
                            //비밀번호 확인란 공백 확인
                            if ($("#password_check").val() === "") {
                                $('#password_check').css('border-color', 'red');
                                $('#pwChk2').html('<b class="c-red">[패스워드확인은 필수정보!]</b>');
                                checkArr[2] = false;
                            }
                            //비밀번호 확인란 유효성검사
                            else if ($("#password").val() !== $("#password_check").val()) {
                                $('#password_check').css('border-color', 'red');
                                $('#pwChk2').html('<b class="c-red">[위에랑 똑같이!!]</b>');
                                checkArr[2] = false;
                            } else {
                                $('#password_check').css('border-color', 'skyblue');
                                $('#pwChk2').html('<b class="c-blue">[참 잘했어요]</b>');
                                checkArr[2] = true;
                            }

                        });

                        //이름 입력값 검증.
                        $('#user_name').on('keyup', function () {
                            //이름값 공백 확인
                            if ($("#user_name").val() === "") {
                                $('#user_name').css('border-color', 'red');
                                $('#nameChk').html('<b class="c-red">[이름은 필수정보!]</b>');
                                checkArr[3] = false;
                            }
                            //이름값 유효성검사
                            else if (!getName.test($("#user_name").val())) {
                                $('#user_name').css('border-color', 'red');
                                $('#nameChk').html('<b class="c-red">[이름은 한글로 ~]</b>');
                                checkArr[3] = false;
                            } else {
                                $('#user_name').css('border-color', 'skyblue');
                                $('#nameChk').html('<b class="c-blue">[참 잘했어요]</b>');
                                checkArr[3] = true;
                            }

                        });

                        //이메일 입력값 검증.
                        const $emailInput = $('#user_email');
                        $emailInput.on('keyup', function () {
                            //이메일값 공백 확인
                            if ($emailInput.val() == "") {
                                $emailInput.css('border-color', 'red');
                                $('#emailChk').html('<b class="c-red">[이메일은 필수정보에요!]</b>');
                                checkArr[4] = false;
                            }
                            //이메일값 유효성검사
                            else if (!getMail.test($emailInput.val())) {
                                $emailInput.css('border-color', 'red');
                                $('#emailChk').html('<b class="c-red">[이메일 형식 몰라?]</b>');
                                checkArr[4] = false;
                            } else {

                                //이메일 중복확인 비동기 통신
                                fetch('/member/check?type=email&value=' + $emailInput.val())
                                    .then(res => res.text())
                                    .then(flag => {
                                        //console.log(flag);
                                        if (flag === 'true') {
                                            $emailInput.css('border-color', 'red');
                                            $('#emailChk').html(
                                                '<b class="c-red">[이메일이 중복되었습니다!]</b>');
                                            checkArr[4] = false;
                                        } else {
                                            $emailInput.css('border-color', 'skyblue');
                                            $('#emailChk').html(
                                                '<b class="c-blue">[사용가능한 이메일입니다.]</b>'
                                            );
                                            checkArr[4] = true;
                                        }
                                    });
                            }

                        });




                    });
                </script>



                <%@ include file="../include/footer.jsp" %>
        </body>

        </html>

 

 

 

 

== 로그인 페이지 만들기

sign-in.jsp

 

 

 

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html lang="ko">

<head>
    <%@ include file="../include/static-head.jsp" %>

    <style>
        .wrap {
            margin: 200px auto;
        }

    </style>
</head>
<body>
    <%@ include file="../include/header.jsp" %>

    <div class="container wrap">
        <div class="row">
            <div class="offset-md-2 col-md-4">
                <div class="card" style="width:200%;">
                    <div class="card-header text-white" style="background: #343A40;">
                        <h2><span style="color: gray;">MVC</span> 로그인</h2>               
                    </div>
                    <div class="card-body">
                        
                        <form action="/member/sign-in" name="sign-in" method="post" id="signInForm"
                        style="margin-bottom: 0;">
                        <table style="cellpadding: 0; cellspacing: 0; margin: 0 auto; width: 100%">
                            <tr>
                                <td style="text-align: left">
                                    <p><strong>아이디를 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;<span id="idCheck"></span></p>
                                </td>
                            </tr>
                            <tr>
                                <td><input type="text" name="account" id="signInId"
                                    class="form-control tooltipstered" maxlength="10"
                                    required="required" aria-required="true"
                                    style="margin-bottom: 25px; width: 100%; height: 40px; border: 1px solid #d9d9de"
                                    placeholder="최대 10자"></td>
                            </tr>
                            <tr>
                                <td style="text-align: left">
                                    <p><strong>비밀번호를 입력해주세요.</strong>&nbsp;&nbsp;&nbsp;<span id="pwCheck"></span></p>
                                </td>
                            </tr>
                            <tr>
                                <td><input type="password" size="17" maxlength="20" id="signInPw"
                                    name="password" class="form-control tooltipstered" 
                                    maxlength="20" required="required" aria-required="true"
                                    style="ime-mode: inactive; margin-bottom: 25px; height: 40px; border: 1px solid #d9d9de"
                                    placeholder="최소 8자"></td>
                            </tr>
                            
                            <!-- 자동 로그인 체크박스 -->
                            <tr>
                                <td>
                                    <label for="auto-login">
                                        <span>
                                        <i class="fa fa-sign-in" aria-hidden="true"></i> 
                                        자동 로그인
                                        <input type="checkbox" id="auto-login" name="isAutoLogin">
                                        </span>
                                    </label>
                                </td>
                            </tr>
                            
                            <tr>
                                <td style="padding-top: 10px; text-align: center">
                                    <p><strong>로그인하셔서 더 많은 서비스를 이용해보세요!</strong></p>
                                </td>
                            </tr>
                            <tr>
                                <td style="width: 100%; text-align: center; colspan: 2;"><input
                                    type="submit" value="로그인" class="btn form-control tooltipstered" id="signIn-btn"
                                    style="background-color: #343A40; margin-top: 0; height: 40px; color: white; border: 0px solid #f78f24; opacity: 0.8">
                                </td>
                            </tr>
                            <tr>
                                <td
                                    style="width: 100%; text-align: center; colspan: 2; margin-top: 24px; padding-top: 12px; border-top: 1px solid #ececec">
    
                                    <a class="btn form-control tooltipstered" href="/member/sign-up"
                                    style="cursor: pointer; margin-top: 0; height: 40px; color: white; background-color: gray; border: 0px solid #388E3C; opacity: 0.8">
                                        회원가입</a>
                                </td>
                            </tr>
                            <tr>
                                <td   style="width: 100%; text-align: center; colspan: 2; margin-top: 24px; padding-top: 12px; border-top: 1px solid #ececec">
    
                                    <a id="custom-login-btn" href="https://kauth.kakao.com/oauth/authorize?client_id=9727a2bba3b021a605228cd4978e3491&redirect_uri=http://localhost/auth/kakao&response_type=code">
                                        <img src="//mud-kage.kakao.com/14/dn/btqbjxsO6vP/KPiGpdnsubSq3a0PHEGUK1/o.jpg" width="300"/>
                                    </a>
                                </td>
                            </tr>
                        </table>
                    </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
    


    <%@ include file="../include/footer.jsp" %>
</body>

 

 

=== 로그인 처리

 

== 적용 하기

 

 

 

 

 

 

 

쿠키(Cookie)와 세션(Session)의 차이 (+캐시(Cache)) — 슬기로운 개발생활 (tistory.com)

 

쿠키(Cookie)와 세션(Session)의 차이 (+캐시(Cache))

쿠키와 세션을 사용하는 이유? HTTP 프로토콜의 특징이자 약점을 보완하기 위해서 사용한다. HTTP 프로토콜의 특징 1. Connectionless 프로토콜 (비연결 지향) 클라이언트가 서버에 요청(Request)을 했을

dev-coco.tistory.com

 

HTTP프로토콜의 무상태성을 해결하기 위해 필요한 쿠키와 세션에 대한 설명 위의 블로그 참고 했습니다.

 

주석 처리 하고 jsp로 넘어간다.

 

로그인 안한사람이 보는 메뉴의 jstl if문 title이 아니라 test 로 수정

 

 

로그인 후 보이는 메뉴 확인

 

=== 로그아웃 세션을 날리면 된다.

 

 

== 인증까지 완료

 

== 인가 맛보기

 

 

 

==

referer 를 활용하여 클라이언트가 로그인 성공시 방금 접근했던 URI 로 바로 접속 될수 있도록 하기

 

 == 인가는 내일 이어서.