티스토리 뷰

웹 개발/SpringBoot

[Spring Boot] 로그인 구현

스톤승현 2022. 11. 10. 16:28

오늘의 문제

@ResponseBody
String MemberController.postLogin(UserEntity user)
-> 주소 : /member/login
-> 방식 : POST
-> 응답 : MediaType.APPLICATIOM_JSON_VLAUE
-> 기타 : XHR 요청에 대한 응답을 하기 위해 존재하는 매핑
-> 로직 : MemberService.login(...) 메서드 호출 결과에 따라 응답은 따로하지 않고 (return null;)  서비스가 반환하는 값에 따라 단순히 System.out.println(...)을 활용하여  로그인 성공 or 실패 여부를 출력.

Enum<? extends IResult> MemberService.login(UserEntity user)
-> 로직 : 전달 받은 USerEntity 타입 객체 'user'가 가지는 'email' 및 'password'에  대해 이를 두 개의 값과 일치하는 레코드에서 새로운 UserEntity를 SELECT 하여, 이가 null 이면 로그인 실패, 어떠한 객체가 전달되었다면 로그인 성공으로 판정하는 로직을 구현하시오.

 

- MemberController

 @RequestMapping(value = "login",
            method = RequestMethod.GET,
            produces = MediaType.TEXT_HTML_VALUE)
    public ModelAndView getLogin() {
        ModelAndView modelAndView = new ModelAndView("member/login");

        return modelAndView;
    }
    
@RequestMapping(value = "login",
        method = RequestMethod.POST,
        produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String postLogin(UserEntity user) {
    Enum<?> result = this.memberService.login(user);
    JSONObject responseObject = new JSONObject();
    responseObject.put("result", result.name().toLowerCase());
    return responseObject.toString();
}

 

- MemberService

public Enum<? extends IResult> login(UserEntity user) {
    UserEntity existingPasswordAuth = this.memberMapper.selectUserByEmails(
            user.getEmail(), CryptoUtils.hashSha512(user.getPassword()));

    if (existingPasswordAuth != null) {
        System.out.println("로그인 성공");
        return CommonResult.SUCCESS;
    }
        return CommonResult.FAILURE;

}

- IMemberMapper

UserEntity selectUserByEmails(String email, String password);

- MemberMapper.xml

<select id="selectUserByEmails"
        resultType="dev.shlee.studymemberbbs.entities.member.UserEntity">
    SELECT `email`             AS `email`,
           `password`          AS `password`,
           `nickname`          AS `nickname`,
           `name`              AS `name`,
           `contact`           AS `contact`,
           `address_postal`    AS `addressPostal`,
           `address_primary`   AS `addressPrimary`,
           `address_secondary` AS `addressSecondary`,
           `registered_on`     AS `registeredOn`
    FROM `study_member`.users
    WHERE BINARY `email` = #{email}
      AND `password` = #{password}
    LIMIT 1
</select>

- login.html

<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>스터디 - 로그인</title>
    <th:block th:replace="~{fragments/head :: common}"></th:block>
    <script defer th:src="@{/member/resources/scripts/login.js}"></script>
    <link rel="stylesheet" th:href="@{/member/resources/stylesheets/login.css}">
</head>
<body>
<th:block th:replace="~{fragments/body :: header}"></th:block>
<th:block th:replace="~{fragments/body :: cover}"></th:block>
<main class="--main">
    <form class="form" id="form">
        <div class="title-container">
            <h1 class="title">로그인</h1>
        </div>
        <table class="table">
            <tbody>
            <tr>
                <th>이메일</th>
                <td>
                    <label class="label email">
                        <span hidden>이메일</span>
                        <input class="--object-input input" maxlength="50" name="email"
                               placeholder="이메일 주소를 입력해 주세요." type="email">
                    </label>
                </td>
            </tr>
            <tr>
                <th>비밀번호</th>
                <td>
                    <label class="label password">
                        <span hidden>비밀번호</span>
                        <input class="--object-input input" maxlength="50" name="password"
                               placeholder="비밀번호를 입력해 주세요." type="password">
                    </label>
                </td>
            </tr>
            <tr class="warning-row" rel="warningRow">
                <th></th>
                <td>
                    <span class="warning">
                        <i class="icon fa-solid fa-triangle-exclamation"></i>
                        <span class="text">이메일을 입력해주세요.</span>
                    </span>
                </td>
            </tr>
            <tr>
                <th></th>
                <td>
                    <input class="--object-button" name="login" type="submit" value="로그인">
                </td>
            </tr>
            <tr>
                <th></th>
                <td>
                    <a>아직 계정이 없으신가요?</a><a class="link" href="#">회원가입</a>
                </td>
            </tr>
            <tr>
                <th></th>
                <td>
                    <a>이메일을 잊으셨나요?</a><a class="link"  href="#">이메일 찾기</a>

                </td>
            </tr>
            <tr>
                <th></th>
                <td>
                    <a>비밀번호를 잊으셨나요?</a><a class="link"  href="#">비밀번호 재설정 하기</a>
                </td>
            </tr>
            </tbody>
        </table>
    </form>
</main>
<th:block th:replace="~{fragments/body :: footer}"></th:block>
</body>
</html>

- login.css

@charset "UTF-8";

#form {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    width: 100%;
    max-width: 30rem;
    margin: 5rem 2rem;
}

#form > .title-container > .title {
    font-size: 2rem;
    font-weight: 500;
    margin-bottom: 2.5rem;
}

#form > .table > tbody > tr > td > .--object-button {
    width: 100%;
    margin-top: 0.25rem;

}

#form > .table > tbody > tr > td > .link {
    margin-left: 0.5rem;
    text-decoration: none;
    color: inherit;
}

#form > .table > tbody > .warning-row .warning {
    background-color: rgb(231, 76, 60);
    color: rgb(255, 255, 255);
    margin-top: 0.5rem;
    padding: 1rem 1rem;
    border-radius: 0.375rem;
    font-size: 0.9rem;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
}

#form > .table > tbody > .warning-row {
    display: none;
}

#form > .table > tbody > .warning-row.visible {
    display: table-row;
}

- login.js

const Warning = {
    getElementById: () => form.querySelector('[rel="warningRow"]'),
    show: (text) => {
        const warningRow = Warning.getElementById();
        warningRow.querySelector('.text').innerText = text;
        warningRow.classList.add('visible');

    },
    hide: () => Warning.getElementById().classList.remove('visible')
};

form.onsubmit = (e) => {
    e.preventDefault();
    Warning.hide();

    if (form['email'].value === '') {
        Warning.show('이메일 가온나.');
        form['email'].focus();
        return;
    }
    if (form['password'].value === '') {
        Warning.show('비번 가와.');
        form['password'].focus();
        return;
    }
    Cover.show('로그인 중 입니다.\n\n 잠시만 기다려 주세요.')
    const xhr = new XMLHttpRequest();
    const formData = new FormData();
    formData.append('email', form['email'].value);
    formData.append('password', form['password'].value);
    xhr.open('POST', './login');
    xhr.onreadystatechange = () => {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            Cover.hide();
            if (xhr.status >= 200 && xhr.status < 300) {
                const responseObject = JSON.parse(xhr.responseText);
                switch (responseObject['result']) {
                    case'success':
                        alert('로그인 성공.')
                        break;
                    case'failure':
                        alert('로그인 실패.')
                        break;
                    default:
                        Warning.show('기다리라');
                }
            }
        }
    };
    xhr.send(formData);

}

정상적인 패스워드를 입력하였을 때
다른 패스워드를 입력하였을 때

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/04   »
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
글 보관함