[ReSeller Project] 특정 리소스에 액세스하지 못하도록 제한

홍정완·2022년 10월 17일
0

ReSeller Project

목록 보기
12/15
post-thumbnail

이번 포스팅에서는 회원 권한에 따른 특정 핸들러에 접근 제한을 설정해 보자.



본 프로젝트는 회원 가입 시, 임의의 토큰을 포함하는 URL이 전송되며 전송된 URL을 클릭하면 인증이 완료된다.


무분별한 회원가입과 유령회원을 방지하기 위해 회원 권한을 총 3개의 UserLevel로 분리했다.


  • 이메일 인증 전 - UNAUTH (판매/구매와 관련된 기능 제한)
  • 이메일 인증 완료 - AUTH (유저 서비스)
  • 관리자 - ADMIN (관리자 기능)



권한 설정 과정


[ReSeller Project] 반복되는 부가기능을 공통적으로 처리해 보자에서 구현한 LoginCheck 어노테이션은 아래와 같다.


@Retention(RUNTIME)
@Target(METHOD)
public @interface LoginCheck {

   UserLevel authority() default UserLevel.UNAUTH;
}

default 값이 UNAUTH로 설정되어 있다.



우선 아래와 같이 enum 클래스를 먼저 구현해 주자.

public enum UserLevel {
    UNAUTH, AUTH, ADMIN
}



그 후, [ReSeller Project] 반복되는 부가기능을 공통적으로 처리해 보자에서 작성한 LoginCheckInterceptor에 아래와 같은 코드를 추가하자.

@Component
@RequiredArgsConstructor
public class LoginCheckInterceptor implements HandlerInterceptor {

    ...

    @Inject
    private Environment environment;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            LoginCheck loginCheck = handlerMethod.getMethodAnnotation(LoginCheck.class);

            ... 

            UserLevel auth = loginCheck.authority();

			// 계층 검사
            switch (auth) {
                case ADMIN:
                    adminUserLevel();
                    break;

                case AUTH:
                    authUserLevel();
                    break;
            }
        }
        ...
    }

    /**
     * 현재 USER의 권한(UserLevel)이 AUTH 인지 체크
     * 해당 리소스는 ADMIN과 AUTH는 접근 가능 -> UNAUTH 경우 제한
     */
    private void authUserLevel() {
        UserLevel auth = sessionLoginService.getUserLevel();
        if (auth == UserLevel.UNAUTH) {
            throw new NotAuthorizedException("해당 리소스에 대한 접근 권한이 존재하지 않습니다.");

        }
    }

    /**
     * 현재 USER의 권한(UserLevel)이 ADMIN 인지 체크
     * ADMIN 외 다른 권한은 해당 요청 제한
     */
    private void adminUserLevel() {
        UserLevel auth = sessionLoginService.getUserLevel();
        if (auth != UserLevel.ADMIN) {
            throw new NotAuthorizedException("해당 리소스에 대한 접근 권한이 존재하지 않습니다.");
        }
    }
}

여기서 주의할 점은 권한 검사 외에도 계층 처리를 하는 코드를 추가로 구현해야 한다.

@LoginCheck 어노테이션의 경우, 권한이 default 값으로 UNAUTH로 설정되기 때문에 @LoginCheck(authority = UserLevel.AUTH)의 경우 계층 처리가 필요하다.


@LoginCheck(authority = UserLevel.AUTH)가 적용된 핸들러는 UNAUTH만 접근이 불가능하고 ADMIN과 AUTH는 접근이 가능해야 한다. 따라서 switch 문을 통해 계층 검사를 진행하는 코드를 추가했다.



적용 후

 	@LoginCheck(authority = UserLevel.ADMIN)
    @ResponseStatus(HttpStatus.CREATED)
    @PostMapping
    public void createBrand(@Valid @RequestPart SaveRequest requestDto, @RequestPart(required = false) MultipartFile brandImage) {
        brandService.saveBrand(requestDto, brandImage);
    }
profile
습관이 전부다.

0개의 댓글