JBCrypt로 리팩토링 : 로그인

Feb 20, 2024
JBCrypt로 리팩토링 : 로그인

1. UserRepository에서

package shop.mtcoding.blog.user; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import shop.mtcoding.blog.board.BoardResponse; import java.util.List; @Repository // IoC에 new하는 방법 public class UserRepository { // DB에 접근할 수 있는 매니저 객체 // 스프링이 만들어서 IoC에 넣어둔다. // DI에서 꺼내 쓰기만 하면된다. private EntityManager em; // 컴포지션 // 생성자 주입 (DI 코드) public UserRepository(EntityManager em) { this.em = em; } @Transactional // db에 write 할때는 필수 public void save(UserRequest.JoinDTO requestDTO){ Query query = em.createNativeQuery("insert into user_tb(username, password, email, created_at) values(?,?,?, now())"); query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); query.setParameter(3, requestDTO.getEmail()); query.executeUpdate(); } public User findByUsernameAndPassword(UserRequest.LoginDTO requestDTO) { Query query = em.createNativeQuery("select * from user_tb where username=? and password=?", User.class); // 알아서 매핑해줌 query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); try { // 내부적으로 터지면 터지는 위치를 찾아서 내가 잡으면 됨 User user = (User) query.getSingleResult(); return user; } catch (Exception e) { return null; } } }
 

2. _core.handler 패키지 생성

CustomExceptionHandler 클래스 생성
package shop.mtcoding.blog._core.handler; public class CustomExceptionHandler { }
 
notion image
o o o o o
5번째에서 오류가 터지면 null이 처리하는 첫번쨰 레이어까지 와야함 -. 매우 복잡해짐
가까이에 있으면 상관없음
깊숙하면 문제가 됨
 
따로 exceptionhandler 클래스를 하나 만들어서 try/catch가 터지면 직접 처리하지 않고 throw 날리면 위임해서 뒤로 위임함 컨트롤러가 throw를 날리면 ds까지 감 문제는 우리가 ds를 손을 못됨
이제 모든 에러를 다 throw를 날려서 ds에게 위임 시킬 것 그럼 ds가 위임 받아서 처리할 방법을 제공해줄 것 exceptionhandler를 만들어서 @ControllerAdvice 하나만 붙이면 ds가 처리해줌
 
package shop.mtcoding.blog.user; import jakarta.servlet.http.HttpSession; import lombok.AllArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import shop.mtcoding.blog._core.util.Script; @AllArgsConstructor @Controller // 파일을 리턴함 -> @ResponseBody로 메세지 자체를 리턴 public class UserController { // fianl 변수는 반드시 초기화 되어야 함 private final UserRepository userRepository; // null private final HttpSession session; // @AllArgsConstructor를 사용하면서 필요 없어짐 // public UserController(UserRepository userRepository, HttpSession session) { // this.userRepository = userRepository; // this.session = session; // } // 원래는 get요청이나 예외 post요청하면 됨 // 민감한 정보는 쿼리 스트링에 담아보낼 수 없음 //원래는 get요청이나 예외 post요청하면 됨 //민감한 정보는 쿼리 스트링에 담아보낼 수 없음 @PostMapping("/login") public String login(UserRequest.LoginDTO requestDTO) { // 1. 유효성 검사 if(requestDTO.getUsername().length() < 3) { return "error/400"; } // 2. 모델 필요 select * from user_tb where username=? and password=? User user = userRepository.findByUsernameAndPassword(requestDTO); // DB에 조회할때 필요하니까 데이터를 받음 session.setAttribute("sessionUser", user); return "redirect:/"; } @PostMapping("/join") public @ResponseBody String join(UserRequest.JoinDTO requestDTO) { System.out.println(requestDTO); try{ userRepository.save(requestDTO); } catch (Exception e) { return Script.back("아이디가 중복되었어요"); } return Script.href("/loginForm"); // 메세지를 자바스크립트로 주면 302를 줄 필요 없음 } @GetMapping("/joinForm") // view만 원함 public String joinForm() { return "user/joinForm"; } @GetMapping("/loginForm") // view만 원함 public String loginForm() { return "user/loginForm"; } @GetMapping("/user/updateForm") public String updateForm() { return "user/updateForm"; } @GetMapping("/logout") public String logout() { // 1번 서랍에 있는 uset를 삭제해야 로그아웃이 됨 session.invalidate(); // 서랍의 내용 삭제 return "redirect:/"; } }
 

3. exception 만드는 방법

  • Ex400 이라는 클래스 만들어서 extends Runtiom Exception하면 exception 이 됨
  • 터뜨릴때 throw new Ex400으로 터뜨리고
  • handler에서 Ex400으로 받으면 됨
  • 상태 코드로 클래스 만들면 됨
  • @ControllerAdvice // 비정상적일때 처리하는 응답 에러 컨트롤러 -> view(파일)를 리턴
  • @ResponseBody붙이면 메세지를 리턴
  • @RestControllerAdvice
  • @Controller -> @ResponseBody붙이면 메세지를 리턴
    • package shop.mtcoding.blog._core.handler; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import shop.mtcoding.blog._core.util.Script; @ControllerAdvice // 비정상적일때 처리하는 응답 에러 컨트롤러 -> view(파일)를 리턴 -> @ResponseBody붙이면 됨 // @RestControllerAdvice : 응답을 직접 반환 // @Controller -> @ResponseBody붙이면 됨 public class CustomExceptionHandler { // 어떤 에러가 나타날때 처리할지 -> 분기해야함 @ExceptionHandler(Exception.class) public @ResponseBody String error1(Exception e) { return Script.back(e.getMessage()); } }
package shop.mtcoding.blog.user; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import shop.mtcoding.blog.board.BoardResponse; import java.util.List; @Repository // IoC에 new하는 방법 public class UserRepository { // DB에 접근할 수 있는 매니저 객체 // 스프링이 만들어서 IoC에 넣어둔다. // DI에서 꺼내 쓰기만 하면된다. private EntityManager em; // 컴포지션 // 생성자 주입 (DI 코드) public UserRepository(EntityManager em) { this.em = em; } @Transactional // db에 write 할때는 필수 public void save(UserRequest.JoinDTO requestDTO){ Query query = em.createNativeQuery("insert into user_tb(username, password, email, created_at) values(?,?,?, now())"); query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); query.setParameter(3, requestDTO.getEmail()); query.executeUpdate(); } public User findByUsernameAndPassword(UserRequest.LoginDTO requestDTO) { Query query = em.createNativeQuery("select * from user_tb where username=? and password=?", User.class); // 알아서 매핑해줌 query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); try { // 내부적으로 터지면 터지는 위치를 찾아서 내가 잡으면 됨 User user = (User) query.getSingleResult(); return user; } catch (Exception e) { throw new RuntimeException("아이디 혹은 비밀번호를 찾을 수 없습니다"); } } }
package shop.mtcoding.blog.user; import jakarta.servlet.http.HttpSession; import lombok.AllArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import shop.mtcoding.blog._core.util.Script; @AllArgsConstructor @Controller // 파일을 리턴함 -> @ResponseBody로 메세지 자체를 리턴 public class UserController { // fianl 변수는 반드시 초기화 되어야 함 private final UserRepository userRepository; // null private final HttpSession session; // @AllArgsConstructor를 사용하면서 필요 없어짐 // public UserController(UserRepository userRepository, HttpSession session) { // this.userRepository = userRepository; // this.session = session; // } // 원래는 get요청이나 예외 post요청하면 됨 // 민감한 정보는 쿼리 스트링에 담아보낼 수 없음 //원래는 get요청이나 예외 post요청하면 됨 //민감한 정보는 쿼리 스트링에 담아보낼 수 없음 @PostMapping("/login") public String login(UserRequest.LoginDTO requestDTO) { // 1. 유효성 검사 if(requestDTO.getUsername().length() < 3) { return "error/400"; } // 2. 모델 필요 select * from user_tb where username=? and password=? User user = userRepository.findByUsernameAndPassword(requestDTO); // DB에 조회할때 필요하니까 데이터를 받음 session.setAttribute("sessionUser", user); return "redirect:/"; } @PostMapping("/join") public @ResponseBody String join(UserRequest.JoinDTO requestDTO) { System.out.println(requestDTO); try{ userRepository.save(requestDTO); } catch (Exception e) { return Script.back("아이디가 중복되었어요"); } return Script.href("/loginForm"); // 메세지를 자바스크립트로 주면 302를 줄 필요 없음 } @GetMapping("/joinForm") // view만 원함 public String joinForm() { return "user/joinForm"; } @GetMapping("/loginForm") // view만 원함 public String loginForm() { return "user/loginForm"; } @GetMapping("/user/updateForm") public String updateForm() { return "user/updateForm"; } @GetMapping("/logout") public String logout() { // 1번 서랍에 있는 uset를 삭제해야 로그아웃이 됨 session.invalidate(); // 서랍의 내용 삭제 return "redirect:/"; } }
notion image
notion image
notion image
notion image
package shop.mtcoding.blog.user; import jakarta.servlet.http.HttpSession; import lombok.AllArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import shop.mtcoding.blog._core.util.Script; @AllArgsConstructor @Controller // 파일을 리턴함 -> @ResponseBody로 메세지 자체를 리턴 public class UserController { // fianl 변수는 반드시 초기화 되어야 함 private final UserRepository userRepository; // null private final HttpSession session; // @AllArgsConstructor를 사용하면서 필요 없어짐 // public UserController(UserRepository userRepository, HttpSession session) { // this.userRepository = userRepository; // this.session = session; // } // 원래는 get요청이나 예외 post요청하면 됨 // 민감한 정보는 쿼리 스트링에 담아보낼 수 없음 //원래는 get요청이나 예외 post요청하면 됨 //민감한 정보는 쿼리 스트링에 담아보낼 수 없음 @PostMapping("/login") public String login(UserRequest.LoginDTO requestDTO) { // 1. 유효성 검사 if(requestDTO.getUsername().length() < 3) { return "error/400"; } // 2. 모델 필요 select * from user_tb where username=? and password=? User user = userRepository.findByUsernameAndPassword(requestDTO); // DB에 조회할때 필요하니까 데이터를 받음 session.setAttribute("sessionUser", user); return "redirect:/"; } @PostMapping("/join") public String join(UserRequest.JoinDTO requestDTO) { System.out.println(requestDTO); try{ userRepository.save(requestDTO); } catch (Exception e) { throw new RuntimeException("아이디가 중복되었어요"); // 위임시키면 로직의 변화없이 오류를 위임하고 끝남 } return "redirect:/loginForm"; } @GetMapping("/joinForm") // view만 원함 public String joinForm() { return "user/joinForm"; } @GetMapping("/loginForm") // view만 원함 public String loginForm() { return "user/loginForm"; } @GetMapping("/user/updateForm") public String updateForm() { return "user/updateForm"; } @GetMapping("/logout") public String logout() { // 1번 서랍에 있는 uset를 삭제해야 로그아웃이 됨 session.invalidate(); // 서랍의 내용 삭제 return "redirect:/"; } }
notion image
notion image
notion image
Share article
RSSPowered by inblog