IT/development

[springBoot] 인터셉터를 통해 메뉴 접근 관리

알 수 없는 사용자 2023. 9. 24. 17:27
반응형

시스템에서는 보안 때문에 로그인한 사용자의 메뉴 접근 범위를 제한해야 한다.

예를 들어 시스템관리자는 시스템관리 메뉴만 접근할 수 있어야 하고 급여관리자는 급여메뉴에만 접근할 수 있어야 한다.

인터셉터를 통해 아래처럼 구현했다.

package kr.dev.common.interceptor;

import kr.dev.cmmn.mapper.CmmnMapper;
import kr.dev.cmmn.model.MenuVo;
import kr.dev.cmmn.service.CmmnService;
import kr.dev.user.model.EmpVO;
import kr.dev.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;

@Slf4j
//권한체크 인터셉터
public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    UserService userService;

    @Autowired
    CmmnService commonService;

    @Autowired
    CmmnMapper cmmnMapper;

    /**
     * 메뉴 접근 권한 체크 인터셉터
     * @param request current HTTP request
     * @param response current HTTP response
     * @param handler chosen handler to execute, for type and/or instance evaluation
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();
        log.info("requestURI = [{}]", requestURI);
        //get sessionInfo
        EmpVO vo = (EmpVO) request.getSession().getAttribute("vo");
        //메뉴 접근 최소 레벨 체크
        String requiredAuthLevel = getMenuRequiredAuthLevel(requestURI);

        /*****관리자인 경우****************************/
        if (Integer.parseInt(vo.getEmpAuthLevel()) >= Integer.parseInt(requiredAuthLevel)) {
            //메뉴 접근가능 여부 체크
            if (userHasMenuAccess(vo.getEmpId(), requestURI)) {
                return true;
            //관리자이지만 접근할 수 없는 메뉴
            } else {
                log.info("권한은 있으나 메뉴 접근 권한이 없습니다.");
                response.sendRedirect("/"); // 또는 다른 접근 거부 페이지로 리다이렉트
                return false;
            }
        /*****관리자가 아닌 경우****************************/
        } 
        log.info("관리자만 접근할 수 있는 메뉴입니다.");
        response.sendRedirect("/"); // 또는 다른 접근 거부 페이지로 리다이렉트
        return false;
    }

    /**
     * 메뉴접근에 필요한 최소 레벨 체크
     * @param requestURI
     * @return
     */
    private String getMenuRequiredAuthLevel(String requestURI) {

        String authLevel = "";
        //시스템 메뉴
        if (requestURI.startsWith("/cmmn/")) {
            authLevel = "2";
        //연차메뉴
        } else if (requestURI.startsWith("/annual/")) {
            authLevel = "1";
        //그 외
        } else {
            authLevel = "2";
        }
        return authLevel;
    }

    /**
     * 사용자의 메뉴접근 권한 체크
     * @param empId
     * @param requestURI
     * @return
     */
    private boolean userHasMenuAccess(String empId, String requestURI) {
        //사용자와 매핑된 메뉴 목록 조회
        List<MenuVo> menuList = cmmnMapper.selectUserMenuCodes(empId);

        if (menuList != null && menuList.size() > 0) {
            //접근하려는 메뉴가 사용자와 매핑된 메뉴에 있는 경우
            for (MenuVo menuVo : menuList) {
                if (requestURI.contains(menuVo.getMenuUrl())) {
                    return true;
                }
            }
        }
        return false;
    }
}

현재 모드 메뉴는 관리자 이상만 접근할 수 있는 상태이다.

세션에서 권한레벨을 가져와 로그인한 사용자가 관리자인지 체크한다.

관리자더라도 본인과 매핑된 메뉴가 아니면 접근할 수 없기에 현재 접근하려는 메뉴가 본인의 아이디와 매핑된 경우에만 통과시키는 로직이다.

개인 스터디 기록을 메모하는 공간이라 틀린점이 있을 수 있습니다.

틀린 점 있을 경우 댓글 부탁드립니다.

반응형