Spring boot 로그인, 회원가입(3)

jjuya·2023년 12월 21일
0
post-thumbnail

회원가입

1. Controller 작성

@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 메소드도 함께 생성함

2. service 작성

@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());
        }
    } 
} 

비밀번호 인코딩후 저장하기


페이지 생성전 포스트맨으로 먼저 확인해보자!
회원가입 성공

가입한 아이디가 존재 할 경우

3. join.html

<!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에 보내는 작업을 진행할 예정

1. Controller

@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토큰을 쿠키에 저장해서 클라이언트에게 넘겨준다!
쿠키에 저장하는건 클라이언트쪽에서 맞는거 같다
이부분은 추후 수정이 필요해보인다

2. Service

	@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토큰을 전달해준다.

3. login.html

<!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>

로그인 완료!

profile
Review the Record⭐

0개의 댓글