개발 ON
  • [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에 있는 데이터다.

     

    로그인에 성공할 경우 해당 회원이 가진 권한을 저장하게 된다.

     

    이전에 생각해뒀던 바보같은 로직은 아래와 같다.

     

    1. 비공개 여부 컬럼을 조건문으로 걸지 않은 데이터를 뽑아온다.
    2. 루프를 돌려 권한과 비공개 여부 컬럼 확인 후 일치하면 remove 시킨다.

     

    그리고 수정한 로직은 아래와 같다.

     

    1. 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
    댓글