package com.mysite.sbb.user;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
public class SiteUser {
@Id //기본키
@GeneratedValue(strategy = GenerationType.IDENTITY) //자동 증가
private Long id;//long타입(int보다 큰 정수)
@Column(unique = true) //유니크키 설정 , 중복 불가
private String username;
private String password;
@Column(unique = true)//유니크키 설정 , 중복 불가
private String email;
}
h2-console을 확인하면 Entity로 설정한 테이블들이 생성된것이 확인된다.
하지만 사용은 불가능하므로 Repository를 만들어서 사용하도록 한다.
UserRepository
package com.mysite.sbb.user;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<SiteUser, Long> {
}
비밀번호 암호화
//암호화 객체
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
UserService 생성
package com.mysite.sbb.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepo;
public SiteUser create(String username, String email, String password) {
SiteUser user = new SiteUser();//SiteUser로 리턴하게 함
user.setUsername(username);//아이디 저장
user.setEmail(email);//이메일 저장
//비밀번호 암호화하기 (암호화 객체 필요함)
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); //암호화
user.setPassword(passEncoder.encode(password));//encode()암호화 메소드
this.userRepo.save(user);//유저 객체를 저장하기
return user;
}
}
User 서비스에는 User 리포지터리를 사용하여 User 데이터를 생성하는 create 메서드를 추가했다.
이 때 사용자의 비밀번호는 보안을 위해 반드시 암호화하여 저장해야 한다.
암호화를 위해 시큐리티의 BCryptPasswordEncoder 클래스를 사용하여 암호화하여 비밀번호를 저장했다.
회원가입 폼(유효성 검사)
UserCreateForm 생성
package com.mysite.sbb.user;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UserCreateForm {
@Size(min = 3, max =25, message = "ID는 3~25자까지 사용가능!")
@NotEmpty(message = "사용자ID는 필수 항목입니다.")
private String username;
@NotEmpty(message = "비밀번호는 필수 항목입니다.")
private String password1;
@NotEmpty(message = "비밀번호 확인은 필수 항목입니다.")
private String password2;
@NotEmpty(message = "이메일은 필수항목입니다.")
@Email
private String email;
}
email 속성에는 @Email 이 적용하여 해당 속성의 값이 이메일형식과 일치하는지를 검증한다.
공백일 경우에는 에러 메세지 출력
min 최소길이 , max 최대길이
UserController 생성
package com.mysite.sbb.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/signup")
public String signup(UserCreateForm userCreateForm) {
return "signup_form";
}
}
signup_form.html생성 후 내용 생성
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="layout::head"></head>
<body>
<nav th:replace="layout::nav"></nav>
<div class="my-3 border-bottom">
<div>
<h4>회원가입</h4>
</div>
</div>
<form
th:action="@{/user/signup}"
th:object="${userCreateForm}"
method="post"
>
<div th:replace="layout::formErrors"></div>
<div class="mb-3">
<label for="username" class="form-label">사용자ID</label>
<input type="text" th:field="*{username}" class="form-control" />
</div>
<div class="mb-3">
<label for="password1" class="form-label">비밀번호</label>
<input type="password" th:field="*{password1}" class="form-control" />
</div>
<div class="mb-3">
<label for="password2" class="form-label">비밀번호 확인</label>
<input type="password" th:field="*{password2}" class="form-control" />
</div>
<div class="mb-3">
<label for="email" class="form-label">이메일</label>
<input type="email" th:field="*{email}" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">회원가입</button>
</form>
</body>
</html>
에러없이 출력되는지 확인하기
컨트롤러에서 userCreateForm객체가 signup으로넘어가는 데
폼의 필드 변수 값이 들어감
그리고 네브바에 회원가입 추가한다
<li class="nav-item">
<a class="nav-link" href="#">로그인</a>
</li>
<li class="nav-item">
<a class="nav-link" th:href="@{/user/signup}">회원가입</a>
</li>
UserController - 회원가입 처리 수정
//회원가입 처리
@PostMapping("/signup")
public String signup(@Valid UserCreateForm userCreateForm,BindingResult result) {
if (result.hasErrors()) {
return "signup_form";
}
//패스워드 확인 (같지 않을 경우)
if(!userCreateForm.getPassword1().equals(userCreateForm.getPassword2())) {
result.rejectValue("password2", "passwordInCorrect","2개의 패스워드가 일치하지 않습니다");
return "signup_form";
}
//DB에 저장하기
userService.create(userCreateForm.getUsername(),
userCreateForm.getEmail(),
userCreateForm.getPassword1());
return "redirect:/"; //기본페이지로 이동
}
password2의 필드 변수 에러임
passwordInCorrect는 이름
2개의 패스워드가 일치하지 않습니다 의 메세지를 출력한다
테스트하기
1. 공백으로 작성 시
2. 비밀번호 1과 2가 일치하지 않을 경우
3. 정상적으로 모든 정보를 입력했을 경우
-> 기본페이지로 이동
-> DB저장까지 확인
패스워드는 저장할 때 암호화를 해서 저장하기 때문에 저렇게 나옴
한 명 더 회원가입 후 hong과 동일하기 비밀번호를 설정해봄
비밀번호는 동일해도 암호화는 다르게 된다.
마지막으로 아직 처리되지 않은게 있음.
이미 가입되어있는 id나 같은 email로 회원가입 시도할 경우 아래와 같은 오류가 발생한다.
노란 부분이 어떤 에러인지 말해줌
trycatch문 추가로 에러 발생 시 에러 메세지 출력하게 코드 수정함
//회원가입 처리
@PostMapping("/signup")
public String signup(@Valid UserCreateForm userCreateForm,BindingResult result) {
if (result.hasErrors()) {
return "signup_form";
}
//패스워드 확인 (같지 않을 경우)
if(!userCreateForm.getPassword1().equals(userCreateForm.getPassword2())) {
result.rejectValue("password2", "passwordInCorrect","2개의 패스워드가 일치하지 않습니다");
return "signup_form";
}
//DB에 저장하기
try {
userService.create(userCreateForm.getUsername(),
userCreateForm.getEmail(),
userCreateForm.getPassword1());
} catch (DataIntegrityViolationException e) {
result.reject("signupFailed","이미 등록된 사용자입니다.");
return "signup_form";
} catch (Exception e) {
e.printStackTrace(); //콘솔에 에러 메세지 출력
result.reject("signupFailed","예상치 못한 에러가 발생했습니다.");
return "signup_form";
}
return "redirect:/"; //기본페이지로 이동
}
테스트하기
이미 가입되어있는 사용자로 회원가입 시도 시
'BACKEND > SpringBoot' 카테고리의 다른 글
로그아웃 처리 (0) | 2023.11.10 |
---|---|
로그인 구현 (0) | 2023.11.10 |
스프링 시큐리티 (0) | 2023.11.10 |
답변 개수 표시 (0) | 2023.11.09 |
게시물에 일련번호 추가하기 (0) | 2023.11.09 |