- [Spring] 공개/비공개글2024년 11월 03일 17시 37분 40초에 업로드 된 글입니다.작성자: 이주여이
게시판에 글 등록할 때 ‘비밀글 여부’에 체크박스 활성화를 시킨 경우 Spring Security에서 ROLE 확인 후 서버 내부에서 해당 게시글 표출 안되게 끔 하는 작업이다.
아무래도 페이지네이션이랑 같이 작업해야하는 부분이다보니 처음에 화면 단에서 Spring Security 써서 비밀 글 표출 안되게 하는 방법을 적용해봤는데 그럼 화면 단에서 페이지네이션도 해당 부분을 처리해야하는거라 그럴바엔 서버에서 처리하자.. 이렇게 생각하게 되었다.
사실 삽질을 좀 하긴 했는데(;;) 다시 한번 리마인드 해보니 굉장히 쉬운 작업이였다..
일단 Controller 단에서 아래 부분을 호출해서 로그를 찍어보자.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // MyUserDetails myUserDetails = (MyUserDetails) authentication.getPrincipal();
// 비회원 권한 - ROLE_ANONYMOUS authentication = AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=5FCA5BBA31A0814522894CB8A314D457], Granted Authorities=[ROLE_ANONYMOUS]] // ADMIN 계정 권한 - ROLE_ADMIN authentication = UsernamePasswordAuthenticationToken [Principal=com.project.homepage.security.MyUserDetails@2bfc4e6f, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=5FCA5BBA31A0814522894CB8A314D457], Granted Authorities=[ROLE_ADMIN]]
참고로 ADMIN 권한은 DB에 있는 데이터다.
로그인에 성공할 경우 해당 회원이 가진 권한을 저장하게 된다.
이전에 생각해뒀던
바보같은 로직은 아래와 같다.- 비공개 여부 컬럼을 조건문으로 걸지 않은 데이터를 뽑아온다.
- 루프를 돌려 권한과 비공개 여부 컬럼 확인 후 일치하면 remove 시킨다.
그리고 수정한 로직은 아래와 같다.
- mapper 호출 시 if문으로 권한이 익명 사용자일 경우 비밀 글을 걸러낸다.
@GetMapping("/list") public String main(@RequestParam(name = "page", required = false, defaultValue = "1") int page, @RequestParam Map<String, Object> requestMap, Model model) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String role = getRole(authentication.getAuthorities()); String code = (String) requestMap.get("code"); String title = getTitle(code); String url = "board/list"; int amount = 10; int offset = (page == 1 ? 0 : (page - 1) * amount); requestMap.put("offset" , offset); requestMap.put("amount" , amount); requestMap.put("role" , role); List<Map<String, Object>> boardGet = service.boardGet(requestMap); int boardGetCnt = service.boardGetCnt(requestMap); Pagination pagination = new Pagination(page, amount, boardGetCnt); model.addAttribute(Const.DATA , boardGet); model.addAttribute(Const.ARTICLE_TITLE , title); model.addAttribute(Const.PAGINATION , pagination); model.addAttribute(Const.SEARCH_DATA , requestMap); return url; }
<select id="boardGet" parameterType="map" resultType="map"> SELECT ROW_NUMBER() OVER(ORDER BY A.IBOARD DESC) ROWNUMBER, A.IBOARD, A.ICODE, A.TITLE, (SELECT NAME FROM tbl_code WHERE ICODE = A.GENRE) GENRE, IFNULL(C.NAME, '') TUMBNAIL, IFNULL(A.YOUTUBE_ID, '') YOUTUBE_ID, A.CREATED_AT, A.SEC_YN FROM tbl_board A INNER JOIN tbl_code B ON A.ICODE = B.ICODE LEFT JOIN tbl_thumbnail C ON A.IBOARD = C.IBOARD WHERE A.DEL_YN = 'N' AND A.ICODE = #{code} <if test="search != null and search != ''"> AND A.TITLE LIKE CONCAT('%', #{search}, '%') </if> <if test="role == 'ROLE_ANONYMOUS'"> AND SEC_YN = 'N' </if> ORDER BY A.IBOARD DESC LIMIT #{offset}, #{amount} </select>
<select id="boardGetCnt" parameterType="map" resultType="int"> SELECT COUNT(*) FROM tbl_board WHERE DEL_YN = 'N' AND ICODE = #{code} <if test="search != null and search != ''"> AND A.TITLE LIKE CONCAT('%', #{search}, '%') </if> <if test="role == 'ROLE_ANONYMOUS'"> AND SEC_YN = 'N' </if> ORDER BY CREATED_AT DESC </select>
테스트해보자.
SELECT sec_yn AS '비공개 여부', title AS '제목' FROM tbl_board WHERE icode = 'B003' AND sec_yn = 'Y';
로그인 전 익명 사용자로 들어올 경우엔 비밀글이 보이지 않는다.
ADMIN 권한 계정으로 로그인을 할 경우엔 비공개 글이 표출된다.
+
try { Map<String, Object> boardSelect = service.boardSelect(requestMap); String code = (String) boardSelect.get("icode"); String secYn = (String) boardSelect.get("sec_yn"); String role = getRole(); requestMap.put("role", role); if(secYn.equals("Y") && role.equals(Const.ROLE_ANONYMOUS)) { throw new AccessDeniedException("권한이 없습니다."); } List<Map<String, Object>> prevPost = service.prevPostGet(requestMap); List<Map<String, Object>> nextPost = service.nextPostGet(requestMap); String title = getTitle(code); boardSelect.put("article_title" , title); boardSelect.put("contents" , commonmarkUtil.markdown((String) boardSelect.get("contents"))); model.addAttribute(Const.PREV_POST , prevPost); model.addAttribute(Const.NEXT_POST , nextPost); model.addAttribute(Const.DATA , boardSelect); return "board/read"; } catch(AccessDeniedException e) { return "access-denied"; }
익명 사용자가 주소창에서 비공개 글 상세보기 url을 호출할 경우에는 AccessDeniedException 예외를 던지고 해당 예외를 잡은 catch문에서 access-denied 페이지로 이동하게 끔만 해놨다. 바로 예외를 던져버리기 때문에 데이터를 받아 보내진 않지만 해당 방법은 좋은 방법은 아닌 것 같고 다른 방법을 찾아봐야 할 듯 하다. 레퍼런스 안찾아봐서 아직 잘 모름..
'Study > Spring' 카테고리의 다른 글
[Spring] CustomExceptionController (0) 2024.11.29 [Spring] 검색 결과 미리보기 (0) 2024.11.17 [Spring] RSS(XML) Parsing (0) 2024.09.21 다음글이 없습니다.이전글이 없습니다.댓글