@RequiredArgsConstructor
@RestController
public class UserController {
private final UserService userservice;
@PostMapping("/register")
public ResponseEntity<?> join(@RequestBody @Valid UserRequest.JoinDTO request, Error error) {
userservice.join(request);
return ResponseEntity.ok( ApiUtils.success(null) );
}
@PostMapping("/check")
public ResponseEntity<?> check(@RequestBody @Valid UserRequest.JoinDTO requestDTO, Error error) {
userservice.checkEmail(requestDTO.getEmail());
return ResponseEntity.ok( ApiUtils.success(null) );
}
회원가입 진행시 이미 가입된 아이디가 있는지 확인을 위해 check 메소드도 함께 생성함
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authenticationManager;
public void checkEmail(String email) {
// 동일한 이메일이 있는지 확인.
Optional<User> users = userRepository.findByEmail(email);
if(users.isPresent()) {
throw new Exception400("이미 존재하는 이메일 입니다. : " + email);
}
}
@Transactional
public void join(UserRequest.JoinDTO requestDTO) {
checkEmail(requestDTO.getEmail());
String encodedPassword = passwordEncoder.encode( requestDTO.getPassword());
requestDTO.setPassword(encodedPassword);
try {
userRepository.save(requestDTO.toEntity());
}catch (Exception e){
throw new Exception500(e.getMessage());
}
}
}
비밀번호 인코딩후 저장하기
페이지 생성전 포스트맨으로 먼저 확인해보자!
회원가입 성공
가입한 아이디가 존재 할 경우
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Join Form</title>
</head>
<body>
<div class="memberWrap">
<div class="inner">
<h1>Join</h1>
<form id="joinForm">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required><br><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required><br><br>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required><br><br>
<label for="phoneNumber">PhoneNumber:</label>
<input type="text" id="phoneNumber" name="phoneNumber" required><br><br>
<input type="submit" value="Submit">
</form>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('joinForm');
form.addEventListener('submit', async function(e) {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const username = document.getElementById('username').value;
const phoneNumber = document.getElementById('phoneNumber').value;
const data = {
email,
password,
username,
phoneNumber
};
try {
const response = await fetch('http://localhost:8080/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.success()) {
alert("회원가입에 성공했습니다!");
window.location.href = '/';
} else {
alert("Error: " + result.error.message);
}
} catch (error) {
console.error('Error:', error);
}
});
});
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
return null;
}
// 메시지 표시
var message = getQueryVariable("msg");
if (message !== null) {
alert(message);
}
</script>
</body>
</html>
jwt를 발급후 header에 실어 client에 보내는 작업을 진행할 예정
@PostMapping(value = "/login")
public ResponseEntity<?> signin(@RequestBody UserRequest.JoinDTO request, HttpServletResponse response, Error error) {
String jwt = userservice.login(request);
// "Bearer " 접두사 제거
jwt = jwt.replace(JwtTokenProvider.TOKEN_PREFIX, "");
// 쿠키 설정
Cookie cookie = new Cookie("jwtToken", jwt);
cookie.setHttpOnly(true);
cookie.setPath("/"); // 모든 경로에서 쿠키 접근 가능
response.addCookie(cookie);
return ResponseEntity.ok().header(JwtTokenProvider.HEADER, jwt)
.body(ApiUtils.success(null));
}
jwt토큰을 쿠키에 저장해서 클라이언트에게 넘겨준다!
쿠키에 저장하는건 클라이언트쪽에서 맞는거 같다
이부분은 추후 수정이 필요해보인다
@Transactional
public String login(UserRequest.JoinDTO requestDTO) {
// ** 인증 작업.
try{
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
= new UsernamePasswordAuthenticationToken(requestDTO.getEmail(), requestDTO.getPassword());
//사용자의 이메일과 패스워드를 포함한 인증 토큰을 생성합
Authentication authentication = authenticationManager.authenticate(
usernamePasswordAuthenticationToken
);
// CustomUserDetailsService에 loadUserByUsername가 실행됨
// authentication여기에 내 로그인한 정보가 담김
//사용자가 제공한 이메일과 비밀번호로 사용자를 인증하려고 하는것
// ** 인증 완료 값을 받아온다.
CustomUserDetails customUserDetails = (CustomUserDetails)authentication.getPrincipal();
// ** 토큰 발급 - 이 JWT 토큰은 사용자 인증을 통해 확인된 사용자의 정보를 포함
return JwtTokenProvider.create(customUserDetails.getUser());
}catch (Exception e){
// 401 반환.
throw new Exception401("인증되지 않음.");
}
}
사용자를 인증하고 인증된 사용자 정보를 담은 jwt토큰을 전달해준다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<!--<link rel="stylesheet" th:href="@{/css/member.css}">-->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<div class="memberWrap">
<div class="inner">
<h1>Login</h1>
<form id="loginForm">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required><br><br>
<br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<br>
<input type="submit" value="login">
</form>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const form = document.getElementById('loginForm');
form.addEventListener('submit', async function (e) {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const data = {
email,
password
};
try {
const response = await fetch('http://localhost:8080/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (response.ok) {
alert("로그인에 성공했습니다!");
window.location.href = '/';
} else {
alert("Error: " + result.error.message);
}
} catch (error) {
console.error('Error:', error);
}
});
});
</script>
</body>
</html>
로그인 완료!