[스프링 부트] 25. 로그인 구현 - 웹 게시판 v5

KangHo Lee's avatar
Nov 27, 2024
[스프링 부트] 25. 로그인 구현  - 웹 게시판 v5

1. 엔티티

User
@AllArgsConstructor @NoArgsConstructor @Table(name = "user_tb") @Getter @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; // null도 처리하도록 Integer @Column(unique = true, nullable = false) private String username; // 사용자가 ID로 인식하는 필드 @Column(nullable = false) private String password; @Column(nullable = false) private String email; @CreationTimestamp private Timestamp createdAt; }

2. 리포지토리

UserRepository
@Repository @RequiredArgsConstructor public class UserRepository { private final EntityManager em; public User findByUsername(String username) { // username이 db에 있는지 조회하는 쿼리문 Query q = em.createQuery("select u from User u where u.username = :username", User.class); q.setParameter("username", username); try { return (User) q.getSingleResult(); } catch (RuntimeException e) { throw new RuntimeException("아이디 혹은 패스워드가 일치하지 않습니다."); } } }

2-1. 리포지토리 테스트

@Import(UserRepository.class) @DataJpaTest public class UserRepositoryTest { @Autowired private UserRepository userRepository; @Test public void findByUserName_test() { // given String username = "ssar"; // 성공 // String username = "hello"; // 실패 // when User user = userRepository.findByUsername(username); // then, import 는 assertj로 합니다. Assertions.assertThat(user).isNotNull(); } }
  • 테스트는 성공과 실패 모두를 테스트해야 합니다.
  • Assertions는 프로그래밍에서 코드의 특정 조건이 참인지 여부를 검증하기 위해 사용되는 도구입니다.
    • 주로 디버깅 및 테스트 목적으로 사용합니다.

3. 서비스

UserService
@RequiredArgsConstructor @Service public class UserService { private final UserRepository userRepository; public User 로그인(UserRequest.LoginDTO loginDTO) { User userPS = userRepository.findByUsername(loginDTO.getUsername()); // 패스워드 일치 확인 if (!userPS.getPassword().equals(loginDTO.getPassword())) { throw new RuntimeException("아이디 혹은 패스워드가 일치하지 않습니다."); // 개발자를 위한 로그 작성 생략 } return userPS; } }
  • 패스워드 불일치 횟수 등을 개발자가 알기 위한 정보를 개발자만 보이는 로그를 남겨야 합니다.

4. 컨트롤러

@RequiredArgsConstructor @Controller public class UserController { private final UserService userService; private final HttpSession session; @GetMapping("/login-form") public String loginForm() { return "user/login-form"; // user 폴더 안에 있는 view } @PostMapping("/login") public String login(UserRequest.LoginDTO loginDTO) { User sessionUser = userService.로그인(loginDTO); session.setAttribute("sessionUser", sessionUser); return "redirect:/"; } // 포스트맨으로 테스트를 하기 위한 메서드 @ResponseBody @GetMapping("/test/auth") public String testAuth() { User sessionUser = (User) session.getAttribute("sessionUser"); if (sessionUser == null) { return "인증안됨"; } return "인증됨 : " + sessionUser.getUsername(); } }
💡
  • 비밀번호는 쿼리 스트링에 노출되면 안되므로 post 방식 요청을 보냅니다.
  • 비밀번호를 세션에 기록하면 안됩니다.
  • username과 password가 db에 있는 정보와 일치하면 세션에 username을 기록합니다.
💡
로그인 매핑을 /user/login이 아니라 /login으로 하는 이유
→ 로그인 과정은 필터를 거칠 필요가 없기 때문입니다.
 
Share article

devleekangho