[게시판 프로젝트] Spring Security를 이용한 로그인(1) 게시물과 이어서 진행합니다
부트스트랩의 도움을 받아 전체적인 ui를 꾸미기 위해 script와 css추가
thymeleaf도 사용하기 위해 추가
1. 아이디 입력 후 중복체크
2. 패스워드와 패스워드 확인 입력
3. 닉네임 입력 후 중복체크
4. 그 외 성별, 생일 입력
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
<meta charset="utf-8">
<title>회원가입</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link th:href="@{/css/signin.css}" rel="stylesheet">
<link th:href="@{/css/birth.css}" rel="stylesheet">
<!-- default header name is X-CSRF-TOKEN -->
<meta id="_csrf" name="_csrf" th:content="${_csrf.token}"/>
<meta id="_csrf_header" name="_csrf_header" th:content="${_csrf.headerName}"/>
</head>
<body class="text-center">
<form name="registerForm" class="form-signin" th:action="@{/account/register}" method="post" th:object="${register}" onsubmit="return checkAll();">
<a th:href="@{/}"><img class="mb-4" th:src="@{/image/log_icon.png}" alt="로고" width="72" height="57"></a>
<h1 class="h3 mb-3 fw-normal">회원가입</h1>
<hr>
<label th:for="username" class="form-label">이메일(아이디)</label>
<div class="mb-3 abc">
<input type="email" class="form-control mx-1 overlap" id="username" name="username" placeholder="이메일을 입력해 주세요">
<input class="btn btn-outline-primary btn-sm idCheck mx-1" type="button" id="usernameOverlay" onclick="usernameCheck()" value="중복 체크"/>
<input class="btn btn-outline-success btn-sm reType" type="button" id="resetUsername" onclick="reUsername()" disabled value="다시입력"/>
</div>
<div class="mb-3">
<label th:for="password">패스워드</label>
<input onchange="pwSame()" type="password" class="form-control" th:field="*{password}" placeholder="비밀번호를 입력해 주세요">
</div>
<div class="mb-3">
<label for="password_check">패스워드 확인</label>
<input onkeyup="pwSame()" type="password" class="form-control" id="password_check" name="password_check" placeholder="비밀번호를 입력해 주세요">
<span id="pw_check_msg"></span>
</div>
<label th:for="nickname" class="form-label">이름(닉네임)</label>
<div class="mb-3 abc">
<input type="text" class="form-control mx-1 overlap" id="nickname" name="nickname" placeholder="닉네임을 입력해 주세요">
<input class="btn btn-outline-primary btn-sm idCheck mx-1" type="button" id="nicknameOverlay" onclick="nicknameCheck()" value="중복 체크"/>
<input class="btn btn-outline-success btn-sm reType" type="button" id="resetNickname" onclick="reNickname()" disabled value="다시입력"/>
</div>
<label class="mb-3 form-label" for="birth">생년월일</label>
<div class="mb-3" id="birth" onchange="checkAge()">
<div class="birth dropdown">
<select class="form-control" id="year" name="year">
<option value="">년(YY)</option>
<th:block th:each="a: ${#numbers.sequence(2001,1900)}">
<option th:value="${a}" th:text="${a}"></option>
</th:block>
</select>
</div>
<div class="birth mx-1 dropdown">
<select class="form-control" id="month" name="month">
<option value="">월(mm)</option>
<th:block th:each="month: ${#numbers.listFormatInteger(#numbers.sequence(1,12),2)}">
<option class="dropdown-item" th:value="${month}" th:text="${month}"></option>
</th:block>
</select>
</div>
<div class="birth dropdown">
<select class="form-control" id="day" name="day">
<option value="">일(dd)</option>
<th:block th:each="day: ${#numbers.listFormatInteger(#numbers.sequence(1,31),2)}">
<option class="dropdown-item" th:value="${day}" th:text="${day}"></option>
</th:block>
</select>
</div>
<span id="birth_check_msg"></span>
</div>
<div class="mb-3">
<label class="form-label" for="gen">성별</label>
<div class="dropdown" id="gen">
<select onkeyup="checkGender()" class="form-control" id="gender" name="gender">
<option value="">성별</option>
<option th:each="genderValue : ${T(com.example.CUSHProject.enums.Gender).values()}"
th:value="${genderValue.value}"
th:text="${genderValue.title}"></option>
</select>
</div>
</div>
<div class="mb-3">
<button class="w-100 btn btn-lg btn-primary" type="submit">회원가입</button>
</div>
<div class="mb-3">
<a type="button" style="color:white" class="w-100 btn btn-lg btn-secondary" onclick="window.history.back();">취소</a>
</div>
</form>
<!--<script src="https://code.jquery.com/jquery-3.6.0.js"></script>-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript" src="/js/register.js"></script>
</body>
</html>
중복확인
버튼과 다시입력
버튼을 만들어 다시입력 버튼은 비활성화
사용자가 중복확인
버튼을 누를시 ajax를 통해 중복확인
중복이면 중복입니다 라는 alert생성
중복이 아닐 시 confirm으로 사용하시겠습니까를 물어본 후 사용한다면 중복확인
버튼 비활성화, 다시입력
버튼 활성화, input창 readonly로 수정
다시입력
버튼 클릭시 input값 초기화
input을 readOnly로 수정한 이유는 사용자가 사용가능한 아이디를 인가 받은 상태에서 다른 아이디로의 변경을 막기위해
function usernameCheck() {
const username = $("#username").val();
if (username == "") {
alert("아이디를 입력해주세요!. 필수항목입니다.");
$("#username").focus();
return false;
}
$.ajax({
type: "get",
url: "/api/overlap/usernameRegister",
data: {"username": username},
dataType: "JSON",
success: function (result) {
if (result.result == "0") {
if (confirm("이 아이디는 사용 가능합니다. \n사용하시겠습니까?")) {
usernameOverlapCheck = 1;
$("#username").attr("readonly", true);
$("#usernameOverlay").attr("disabled", true);
$("#usernameOverlay").css("display", "none");
$("#resetUsername").attr("disabled", false);
$("#resetUsername").css("display", "inline-block");
}
return false;
} else if (result.result == "1") {
alert("이미 사용중인 아이디입니다.");
$("#username").focus();
} else {
alert("success이지만 result 값이 undefined 잘못됨");
}
},
error: function (request, status,error) {
alert("ajax 실행 실패");
alert("code:" + request.status + "\n" + "error :" + error);
}
});
}
memberEntity에 대해 Repository를 만들어 JPA사용
@Repository
public interface MemberRepository extends JpaRepository<MemberEntity, Long> {
...
//중복가입
boolean existsByUsername(String username);
boolean existsByNickname(String nickname);
}
MemberService
해당 값을 map에 담아 리턴후 해당 값의 결과에 따라 중복여부 체크
//email 중복 검사
public HashMap<String, Object> usernameOverlap(String username) {
HashMap<String, Object> map = new HashMap<>();
map.put("result", memberRepository.existsByUsername(username));
return map;
}
//닉네임 중복 검사
public HashMap<String, Object> nicknameOverlap(String nickname) {
HashMap<String, Object> map = new HashMap<>();
map.put("result", memberRepository.existsByNickname(nickname));
return map;
}
중복일시
사용가능
모든 validate를 통과하고 회원가입 버튼 누를시 해당 form이 post형식으로 전달
BCryptPasswordEncoder
를 통해 패스워드를 암호화 하고 기본적으로 Role를 ROLE_MEMBER
로 세팅 후 JPA를 이용하여 entity에 저장
@Transactional
public Long singUp(MemberDto memberDto) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
memberDto.setPassword(passwordEncoder.encode(memberDto.getPassword()));
memberDto.setRole(Role.ROLE_MEMBER);
return memberRepository.save(memberDto.toEntity()).getId();
}
패스워드는 아래와 같이 인코딩 된 형태로 DB에 저장
다음 포스트에 이어서 작성!