Blog

[Spring][258] 프로젝트 마무리 작업

Category
Author
Tags
PinOnMain
1 more property

1. 검색 기능 업그레이드

기존 페이징 버전(v3)
슬라이스 방식의 버전(v4)
무한 스크롤 기능(is1)
엘라스틱 서치 기능(el1)

2. 프론트엔드 네비게이션 변경

로그인 상태에 따른 UI 변경
비로그인 상태: 로그인 메뉴 표시, 로그아웃 메뉴 숨김
로그인 상태: 로그인 메뉴 숨김, 로그아웃 메뉴 표시
사용자의 역할(Role)에 따른 메뉴 표시 변경
일반 사용자: 도서 검색, 도서 나눔 신청, 마이페이지 접근 가능
관리자: 관리자 전용 메뉴들에 접근 가능
기존 모든 코드에 Model을 통해 권한을 전달하는 건 비효율적 -> AOP를 이용해서 전체를 한꺼번에 처리하는 것을 시도
AOP 적용에 시간이 걸릴 것 같기에 viewController에 하나하나 추가하는 걸로 변경

트러블 슈팅

문제 상황 SecurityUtil.getPrincipal() 메서드가 String 타입의 객체를 반환하고 있지만, 이를 UserDetailsImpl 타입으로 캐스팅하려고 시도했기 때문에 문제가 발생하였다고 한다. String?
이를 해결하기 위해 토큰이 아무것도 없을때에는 어떻게 SecurityContext가 구성되는지 확인할 필요가 있어보인다.
토큰이 없을 때는 위와 같이 securityContextHolder의 authentication.principal에 anonymousUser라는 문자열이 들어간 다는 것을 알 수 있다.
그럼 로직을 2가지로 나누어야한다. string일때와 user일때
토큰이 있을때 ADMIN, USER, 그외에 로그인하지 않아서 토큰이 없을때는 Anonymous로 분류한다.

프론트 layout에 적용

ADMIN -> home, search, User, Admin, Donation, about team 258, logout 보이도록 설정
USER -> home, search, user, donation, about team 258, logout 보이도록 설정
ANONYMOUS -> home, Login, Signup, Search, about team 258 보이도록 설정

logout 기능 구현

@GetMapping("/logoutView") public String logoutView(Model model){ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletResponse response = attributes.getResponse(); /** * 쿠키 삭제 기능 추가 */ Cookie cookie = new Cookie("Authorization", null); cookie.setMaxAge(0); cookie.setPath("/"); response.addCookie(cookie); return "redirect:/"; }
Java
복사
Layout.html
<!-- resources/templates/layout.html --> <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head th:fragment="head"> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> <!-- Bootstrap icons--> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css" rel="stylesheet"/> <!-- Core theme CSS (includes Bootstrap)--> <link href="/css/style.css" rel="stylesheet"/> <!-- Bootstrap core JS--> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@stomp/stompjs@7.0.0/bundles/stomp.umd.min.js"></script> <script> // JavaScript window.addEventListener('load', function () { adjustContentPosition(); }); window.addEventListener('resize', function () { adjustContentPosition(); }); function adjustContentPosition() { var headerHeight = document.querySelector('.index-header') ? document.querySelector('.index-header').offsetHeight : 0; var container = document.querySelector('.index-container'); var contents = document.querySelector('.index-contents'); if (container && contents) { container.style.marginTop = headerHeight + 'px'; contents.style.maxHeight = (100 - (headerHeight / window.innerHeight) * 100) + 'vh'; } } </script> </head> <body class="index-body"> <!-- Navigator --> <!-- Responsive navbar--> <nav class="navbar navbar-expand-lg navbar-dark bg-dark" th:fragment="nav"> <div class="container px-7"> <div class="index-logo"> <a class="navbar-brand" href="/"> <img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd22XUp%2FbtsxriHCYvH%2FwA1ES8jDhbNBzCtYDgK9MK%2Fimg.png" style="filter: invert(90%); height: 35px;width: 55px; padding-right: 5px"> Library App</a> </div> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav ms-auto mb-2 mb-lg-0"> <li class="nav-item"><a class="nav-link active" aria-current="page" href="/">Home</a></li> <li class="nav-item" th:if="${loginUserRole == 'ANONYMOUS'}"><a class="nav-link" id="loginbtn" href="/login">Login</a></li> <li class="nav-item" th:if="${loginUserRole == 'ANONYMOUS'}"><a class="nav-link" id="signupbtn" href="/signup">SignUp</a></li> <li class="nav-item" th:if="${loginUserRole == 'USER' or loginUserRole == 'ADMIN'}"><a class="nav-link" id="logoutbtn" href="/logoutView">Logout</a></li> <!-- Search --> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" id="navbarDropdownSearch" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Search</a> <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownBlog"> <li class="dropdown-item"><a class="dropdown-item" href="/search/v3">BookSearchPage</a></li> <li class="dropdown-item"><a class="dropdown-item" href="/search/v4">BookSearchSlice</a></li> <li class="dropdown-item"><a class="dropdown-item" href="/search/is1">BookSearchIS</a></li> <li class="dropdown-item"><a class="dropdown-item" href="/search/el1">BookElasticSearch</a></li> </ul> </li> <li class="nav-item dropdown" th:if="${loginUserRole == 'USER' or loginUserRole == 'ADMIN'}"> <a class="nav-link dropdown-toggle" id="navbarDropdownUser" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">User</a> <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownBlog"> <li class="dropdown-item"><a class="dropdown-item" id="mypagebtn" href="/mypage">MyPage</a></li> <li class="dropdown-item"><a class="dropdown-item" id="myrentalsbtn" href="/myrentals">MyRentals</a></li> <li class="dropdown-item"><a class="dropdown-item" id="myreservationsbtn" href="/myreservations">MyReservations</a></li> </ul> </li> <li class="nav-item dropdown" th:if="${loginUserRole == 'ADMIN'}"> <a class="nav-link dropdown-toggle" id="navbarDropdownAdmin" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Admin</a> <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownBlog"> <!-- user Controller R,D--> <!-- <li class="dropdown-item"><a class="dropdown-item" id="adminUserBtn" href="/admin/users">Admin Users</a></li>--> <li class="dropdown-item"><a class="dropdown-item" id="adminUserBtn" href="/admin/users/v2">Admin Users</a></li> <!-- admin book controller ( CRUD )--> <li class="dropdown-item"><a class="dropdown-item" id="adminBooksBtn" href="/admin/books">Admin Books</a></li> <!-- admin category controller ( CRUD ) --> <li class="dropdown-item"><a class="dropdown-item" id="adminCategoriesBtn" href="/admin/categories">Admin Categories</a></li> <!-- admin donation controller ( CRUD )--> <li class="dropdown-item"><a class="dropdown-item" id="adminDonationBtn" href="/admin/donation/v3">Admin Donation</a></li> </ul> </li> <li class="nav-item dropdown" th:if="${loginUserRole == 'USER' or loginUserRole == 'ADMIN'}"> <a class="nav-link dropdown-toggle" id="navbarDropdownDonation" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Donation</a> <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownBlog"> <!-- <li class="nav-item"><a class="nav-link" id="userBookDonationEventBtn" href="/users/bookDonationEvent">Book Donation Event List</a></li>--> <li class="dropdown-item"><a class="dropdown-item" id="userBookDonationEventBtn" href="/users/bookDonationEvent/v3">Book Donation Event List</a> </li> <li class="dropdown-item"><a class="dropdown-item" id="userBookApplyCancel" href="/users/bookApplyDonation/cancel">Book Apply Cancel</a></li> </ul> </li> <!-- About us --> <li class="nav-item"><a class="nav-link active" href="/about258">About Team 258</a></li> </ul> </div> </div> </nav> <!-- Header --> <div class="index-header" th:fragment="header"> <div class="index-container1"> <span class="index-text20"><span>Welcome to Library App</span></span> <span class="index-text22"> <span>Have fun with Books and Us</span> </span> </div> </div> <div class="index-contents" th:fragment="content"> <!-- Content goes here --> </div> <div class="index-footer" th:fragment="footer"> <div class="index-container3"> <span class="index-text24"> <span>© 2023 TEAM 258. All rights reserved.</span> </span> </div> </div> </body> </html>
JavaScript
복사

프론트 작업 완료

Admin Login
Login하지 않은 상태
User Login