로그인, 회원가입 기능을 만들고 난 후
로그인할 때 비밀번호가 기억이 나지 않을 때 본인인증을 통한 비밀번호 변경 기능 추가하기
1. 회원가입 기능
+ id 중복체크 기능
+ 비밀번호 입력 시 눈모양 클릭하면 입력 내용 보이기 기능
2. 로그인 기능
+ 비밀번호 입력 시 눈모양 클릭하면 입력 내용 보이기 기능
3. 본인 인증 기능
4. 비밀번호 변경 기능
[로그인] , [회원가입]
1. User.java (Entity만들기)
@Entity
@Data
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String email;
private String pwd;
private String newPassword;
private String name;
private Integer phone;
private Date creDate;
private Integer count;
private UserRole role;
public enum UserRole { //열거형 값
CUSTOMER, // 일반 고객0
ADMIN // 관리자1
}
public String getRole() {
return role.name(); // 열거형 값의 이름을 문자열로 반환
}
}
※ @Data : Data는 접근불가능하게 설정되므로 set, get 메소드를 만들어 줘야하는데 @Data를 넣으면 set, get 메소드를 자동으로 만들어줌. 즉, toString()를 Override하고 있음
2. UserRepository.java 만들기
public interface UserRepository extends JpaRepository<User, Long> {
public User findByEmailAndPwd(String email, String pwd);
public User findByEmail(String email);
public User findById(long id);
List<User> findByEmailAndNameAndPhone(String email,String name, Integer phone);
}
※ extends JpaRepository<User, Long> : JPA Repository 상속받음 , User 테이블의 id를 Long형태로 가져옴
※ List<User> findByEmailAndNameAndPhone(String email,String name, Integer phone);
: User 엔티티에서 email, name, 그리고 phone 필드가 주어진 값과 일치하는 레코드를 모두 찾아내기
3. UserController.java 만들기
@Controller
public class UserController {
@Autowired
UserRepository userRepository;
@Autowired
PasswordEncoder passwordEncoder;
//회원가입
@GetMapping("/signup")
public String signup(Model model) {
return "signup";
}
@PostMapping("/signup")
public String signupPost(@ModelAttribute User user,
@RequestParam(value = "isAdmin", required = false) boolean isAdmin) {
String userPwd = user.getPwd();
String encodePwd = passwordEncoder.encode(userPwd); //비밀번호 암호화
user.setPwd(encodePwd);
user.setCreDate(new Date());
// 사용자 역할 설정 (관리자 or 고객)
User.UserRole userRole = isAdmin ? User.UserRole.ADMIN : User.UserRole.CUSTOMER;
// 사용자 정보 저장
user.setRole(userRole);
user.setCoinDate(new Date(0));
userRepository.save(user);
return "redirect:/";
}
//id중복체크
@GetMapping("/email-check")
@ResponseBody
public String emailCheck(@ModelAttribute User user) {
String email = user.getEmail();
User result = userRepository.findByEmail(email);
if (result != null) { // 값 있음=아이디가 있음=>가입 불가
return "가입불가";
} else { // 값 없음=아이디가 없음=>가입 가능
return "가입가능";
}
}
//로그인
@GetMapping("/signin")
public String signin() {
return "signin";
}
@PostMapping("/signin")
public String signinPost(@ModelAttribute User user, Model model) {
User dbUser = userRepository.findByEmail(user.getEmail());
// 오류
if (dbUser == null) {
model.addAttribute("error", "이메일 또는 비밀번호가 일치하지 않습니다.");
return "signin";
}
String encodedPwd = dbUser.getPwd(); //등록된 암호화비밀번호
String userPwd = user.getPwd(); //입력한 비밀번호
boolean isMatch = passwordEncoder.matches(userPwd, encodedPwd);
if (isMatch) {
// 로그인 성공한 경우 user_info 세션에 넣기
session.setAttribute("user_info", dbUser);
return "redirect:/";
} else {
model.addAttribute("error", "이메일 또는 비밀번호가 일치하지 않습니다.");
return "signin";
}
}
}
4. signup.html / signin.html 만들기
1)signup.html (id 중복체크 기능 추가)
<!DOCTYPE html>
<html lang="en">
<head th:replace="common/head"></head>
<body>
<div th:replace="common/header"> </div>
<nav th:replace="common/nav"></nav>
<div class="title">
<h1>회원가입</h1>
</div>
<div class="signupForm">
<div class="container mt-5">
<div class="row">
<form method="post" action="/signup" id="realsignupForm">
<div class="mb-3">
<label for="email">Email:</label>
<input type="email" class="form-control" id="email" name="email" pattern="[a-z0-9._%+-]+@[a-z]+\.[a-z]{2,}$"
title=" 정확한 이메일 주소를 입력해주세요" placeholder="ex.daram@dotori.com" required>
<button class="btn btnn-primary" type="button" onclick="checkEmail()">중복확인</button>
<span id="duplicateResult"></span>
</div>
<div class="mb-3">
<label for="pwd">Password:</label>
<input type="password" class="form-control" id="pwd" name="pwd" pattern="(?=.*\d)(?=.*[a-zA-Z]).{8,}"
title="영문대소문자/숫자로 이루어진 최소 8글자의 비밀번호를 입력하세요" placeholder="영문대소문자/숫자로 이루어진 최소 8글자의 비밀번호" required>
<i class="fa fa-eye fa-lg eyes" th:attr="onclick='togglePasswordVisibility()'"></i>
</div>
<div class="mb-3">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" name="name" pattern="^[a-zA-Z가-힣]+$"
title="올바른 이름을 입력하세요 ex.홍길동" placeholder="이름" required>
</div>
<div class="mb-3">
<label for="name">Phone:</label>
<input type="text" class="form-control" id="phone" name="phone" pattern="[0-9]{10,11}"
title="10-11자리의 숫자를 '-' 없이 입력하세요" placeholder="휴대전화번호('-'기호 제외 10~11자리)" required>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="isAdmin" name="isAdmin">
<label class="form-check-label" for="isAdmin">관리자</label>
</div>
<div class="d-grid gap-2">
<button class="btn btnn-primary" id="signup" style="width : 250px;">가입하기</button>
</div>
</form>
</div>
</div>
</div>
<script>
// id중복체크
async function checkEmail() {
const email = document.querySelector("[name=email]").value;
const response = await fetch(`/email-check?email=${encodeURIComponent(email)}`);
const result = await response.text();
// 중복 확인 결과에 따라 메시지 표시
const duplicateResultElement = document.getElementById("duplicateResult");
if (result == "가입불가") {
duplicateResultElement.textContent = "중복된 Email입니다.";
duplicateResultElement.style.color = "red";
isEmailValid = false;
} else if (result == "가입가능") {
duplicateResultElement.textContent = "사용 가능한 Email입니다.";
duplicateResultElement.style.color = "green";
isEmailValid = true;
}
updateSignupButtonState();
}
// 비밀번호 보이기표시
function togglePasswordVisibility() {
var $passwordInput = $('#pwd'); // ID를 사용하여 비밀번호 입력란을 선택
if ($passwordInput.attr('type') === 'password') {
$('.eyes').removeClass('fa-eye').addClass('fa-eye-slash');
$passwordInput.attr('type', 'text');
} else {
$('.eyes').removeClass('fa-eye-slash').addClass('fa-eye');
$passwordInput.attr('type', 'password');
}
}
</script>
<div th:replace="common/footer" style="margin-top: 1rem;">
</div>
</body>
</html>
2)signin.html
<!DOCTYPE html>
<html lang="en">
<head th:replace="common/head"></head>
<body>
<div th:replace="common/header"></div>
<nav th:replace="common/nav"></nav>
<div class="title">
<h1>로그인</h1>
</div>
<div class="container mt-5">
<div class="row">
<form method="post" action="/signin">
<div class="mb-3 input-group flex-nowrap">
<span class="input-group-text">💻</span>
<input type="email" class="form-control" id="email" name="email" placeholder="email" title="이메일 형식이어야 합니다" required>
</div>
<div class="mb-3 input-group flex-nowrap">
<span class="input-group-text">🔒</span>
<input type="password" class="form-control" id="pwd" name="pwd" placeholder="password" required>
<i class="fa fa-eye fa-lg eyes" th:attr="onclick='togglePasswordVisibility()'"></i>
</div>
<div th:if="${error}" class="alert alert-danger">
<p th:text="${error}"></p>
</div>
<div class="d-grid gap-2">
<button class="btn btn-primary" id="signin">로그인</button>
</div>
<div class="d-grid gap-2">
<a class="pwdforget" id="pwdforget" href="/pwdforget">비밀번호가 기억나지 않는다면?</a>
</div>
</form>
</div>
</div>
<script>
//비밀번호 눈 클릭하면 보이기
function togglePasswordVisibility() {
var $passwordInput = $('#pwd');
if ($passwordInput.attr('type') === 'password') {
$('.eyes').removeClass('fa-eye').addClass('fa-eye-slash');
$passwordInput.attr('type', 'text');
} else {
$('.eyes').removeClass('fa-eye-slash').addClass('fa-eye');
$passwordInput.attr('type', 'password');
}
}
</script>
</body>
</html>
결과물
본인 인증, 비밀번호 변경 기능은 다음 글을 참고하세요~
'Back-End > Spring boot' 카테고리의 다른 글
[날다프로젝트] Service, Controller 와 Repository / DAO와 DTO (1) | 2024.02.17 |
---|---|
[JAVA][Spring]관리자 페이지 만들기 (1) | 2023.11.01 |
[JAVA][Spring] 본인 인증, 비밀번호 변경하기(2) (2) | 2023.10.27 |