[Spring Boot] 7. Spring Boot Project (Bank v1)_3-2.Fuctions Design_Login & Logout

김미숙's avatar
Mar 27, 2025
[Spring Boot] 7. Spring Boot Project (Bank v1)_3-2.Fuctions Design_Login & Logout

⚠ 로그인만 예외로 보안때문에 get이 아닌 post방식

‼️

application.properties

# utf-8 server.servlet.encoding.charset=utf-8 server.servlet.encoding.force=true # DB spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:mem:test spring.datasource.username=sa spring.datasource.password= spring.h2.console.enabled=true # JPA table create or none spring.jpa.hibernate.ddl-auto=create # query log spring.jpa.show-sql=true # dummy data spring.sql.init.data-locations=classpath:db/data.sql # create dummy data after ddl-auto create spring.jpa.defer-datasource-initialization=true # mustache request expose spring.mustache.servlet.expose-request-attributes=true # mustache session expose spring.mustache.servlet.expose-session-attributes=true # Sql formatter spring.jpa.properties.hibernate.format_sql=true

header

‼️
조건문
  • if → {{#값}}
  • else → {{^값}}
<!DOCTYPE html> <html lang="en"> <head> <title>Bank</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> </head> <body> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="/">Home</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="collapsibleNavbar"> <ul class="navbar-nav"> {{#sessionUser}} <li class="nav-item"> <a class="nav-link" href="#">계좌목록</a> </li> <li class="nav-item"> <a class="nav-link" href="#">계좌생성</a> </li> <li class="nav-item"> <a class="nav-link" href="#">이체하기</a> </li> <li class="nav-item"> <a class="nav-link" href="/logout">로그아웃</a> </li> {{/sessionUser}} {{^sessionUser}} <li class="nav-item"> <a class="nav-link" href="/join-form">회원가입</a> </li> <li class="nav-item"> <a class="nav-link" href="/login-form">로그인</a> </li> {{/sessionUser}} </ul> </div> </div> </nav>
 

home

{{>layout/header}} <!--마진 : mt,mr,ml,mb (1~5) ex) mt-5--> <div class="container mt-2"> <div class="mt-4 p-5 bg-light text-dark rounded-4"> <h1>메타코딩 은행에 오신 것을 환영합니다</h1> <h3> {{#sessionUser}} {{sessionUser.fullname}}님 {{/sessionUser}} </h3> </div> </div> {{>layout/footer}}

UserController

package com.metacoding.bankv1.user; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @RequiredArgsConstructor @Controller public class UserController { private final UserService userService; private final HttpSession session; // 로그인만 조회 시에 예외로 Post @PostMapping("/login") public String login(UserRequest.LoginDTO loginDTO) { User sessionUser = userService.로그인(loginDTO); session.setAttribute("sessionUser", sessionUser); //statefull 스코프: 생명주기 session스코프 > request스코프 return "redirect:/"; } @GetMapping("/login-form") public String loginForm() { return "user/login-form"; } @GetMapping("/join-form") public String joinForm() { return "/user/join-form"; } @PostMapping("/join") public String join(UserRequest.JoinDTO joinDTO) { userService.회원가입(joinDTO); return "redirect:/login-form"; } }
 

UserService

package com.metacoding.bankv1.user; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor @Service public class UserService { private final UserRepository userRepository; @Transactional public void 회원가입(UserRequest.JoinDTO joinDTO) { // 1. 동일 username 있는지 검사 (조회) User user = userRepository.findByUsername(joinDTO.getUsername()); // 2. 있으면 exception 터트리기 if (user != null) throw new RuntimeException("동일한 username이 존재합니다."); // 3. 없으면 회원가입하기 userRepository.save(joinDTO.getUsername(), joinDTO.getPassword(), joinDTO.getUsername()); } public User 로그인(UserRequest.LoginDTO loginDTO) { // 1. 해당 username이 있는지 User user = userRepository.findByUsername(loginDTO.getUsername()); // 2. username, password가 불일치하는 것들을 Filtering if (user == null) { throw new RuntimeException("해당 username이 없습니다."); } if (!(user.getPassword().equals(loginDTO.getPassword()))) { throw new RuntimeException("해당 password가 틀렸습니다."); } // 3. 인증 return user; } }

Login test

  • 로그인 전 화면에는 회원가입과 로그인 메뉴만 나온다
notion image
⬆ 존재하는 user인 ‘ssar’ 로 로그인하면
⬇ 로그인되서 화면에 user의 fullname이 노출되고,
메뉴에 회원가입과 로그인은 나오지 않는다
notion image
 

Logout

UserController

package com.metacoding.bankv1.user; import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @RequiredArgsConstructor @Controller public class UserController { private final UserService userService; private final HttpSession session; @GetMapping("/logout") public String logout() { session.invalidate(); // 안에 있는 걸 전부 다 버림 return "redirect:/"; } // 로그인만 조회 시에 예외로 Post @PostMapping("/login") public String login(UserRequest.LoginDTO loginDTO) { User sessionUser = userService.로그인(loginDTO); session.setAttribute("sessionUser", sessionUser); //statefull 스코프: 생명주기 session스코프 > request스코프 return "redirect:/"; } @GetMapping("/login-form") public String loginForm() { return "user/login-form"; } @GetMapping("/join-form") public String joinForm() { return "/user/join-form"; } @PostMapping("/join") public String join(UserRequest.JoinDTO joinDTO) { userService.회원가입(joinDTO); return "redirect:/login-form"; } }

Login test

  • 로그아웃 click
notion image
⬇ Redirection 되서 home 페이지로 이동하면서,
메뉴에 회원가입과 로그인만 확인된다
notion image
Share article

parangdajavous