어노테이션 기반 권한 관리

2024. 10. 14. 08:26·트러블슈팅

프로젝트에서 커스텀이 가능한 권한부여 기능 요구사항이 들어왔다.

기존 spring security에 의존해서 ROLE 기반으로 관리를 하기에는 제약사항이 많았고 유연하지 못하다라는 생각이 들었다.

그래서 우리는 각 도메인별로 C/R/U/D 각각 접근을 할 수 있는 정책을 만들었고 이 정책들을 모은 집합 권한을 만들어서 유저한테 부여하는 방식으로(AWS를 참고했다) 구성하였다.

수많은 정책들을 전부 관리하고 각 컨트롤러마다 권한을 확인하는일을 하나씩 만드는건 힘들다고 생각해 AOP와 커스텀 어노테이션을 적용해서 구현하기로 하였다.

기본 구성

스프링의 어노테이션을 많이 참고해서 구성을 하였다.

특히 @RequestMapping을 보며 우리도 상위 어노테이션 하나 만들고 정책을 넣고 하위 어노테이션으로 관리하면 되겠다라고 생각해

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface BemsPermission {
	PolicyType[] policyType() default {};
}

@BemsPermission(
	policyType = {PolicyType.CONTROL_POINT_CREATE}
)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ControlPointCreate {
}

@ControlPointCreate
@PostMapping
public ResponseEntity<List<ControlPointCreateResponse>> createControlPoint(@RequestParam Long buildingId,
	@RequestBody @Valid List<ControlPointRequest> controlPointRequests) {
	return new ResponseEntity<>(
		controlPointApplicationService.createControlPoints(buildingId, controlPointRequests), HttpStatus.CREATED);
}

이렇게 구성 한 후 컨트롤러가 호출될 때 aop가 먼저 어노테이션에 있는 PolicyType와 유저가 가지고 있는 PolicyType을 비교해서 권한 체크를 한다.

어노테이션의 상속?

기본적으로 어노테이션은 상속이라는 개념이 없다.

하지만 나는 Spring의 @RequestMapping의 @GetMapping을 보며 GetMapping을 하면 RequestMapping(method = RequestMethod.GET)을 한것과 똑같이 동작하니까 상위의 어노테이션을 부를 수 있구나 라고 생각 했다.

 @After
 public void checkPermission(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        
        // BemsPermission 어노테이션을 메소드에서 가져오기
        BemsPermission permission = method.getAnnotation(BemsPermission.class);
  }

분명히 @ControlPointCreate는 @BemsPermission을 가지고 있는데 permission이 null이 나오고 있었다.

메타 어노테이션

메타 애노테이션이란 애노테이션 위에 붙은 애노테이션이라는 뜻이다. 보통 애노테이션은 클래스나 메소드 앞에 붙지만, 애노테이션 위에도 애노테이션을 또 붙일 수 있다. 이때 애노테이션 위에 붙어있는 애노테이션을 메타 애노테이션이라 한다.

상속관계가 없는 어노테이션에서 상위(?) 어노테이션 즉 메타 어노테이션을 가져오려면 AnnotationUtils 클래스 또는 AnnotatedElementUtils 클래스를 사용하면 된다

MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Method method = signature.getMethod();

BemsPermission permission = AnnotationUtils.findAnnotation(method, BemsPermission.class);

if (permission != null) {
    PolicyType[] policyTypes = permission.policyType();
    for (PolicyType policyType : policyTypes) {
        log.info("Executed method with policy type: {}", policyType);
    }
}

그래서 이렇게 메타 어노테이션을 찾아서 권한을 가져와서 권한 체크를 진행하고 있다.

참고

  • https://velog.io/@potato_song/Java-어노테이션-커스텀-어노테이션-만들기
  • https://velog.io/@chocochip/Meta-Annotation
  • https://wonwoo.me/327
  • https://docs.spring.io/spring-framework/docs/5.1.0.RC1_to_5.1.0.RC2/Spring Framework 5.1.0.RC1/org/springframework/core/annotation/AnnotationUtils.html

'트러블슈팅' 카테고리의 다른 글

Spring Batch processor 이야기  (0) 2024.10.15
연관관계 매핑  (0) 2024.10.15
관제값 조회 디자인 패턴 적용  (1) 2024.10.13
그래프 조회 속도 개선  (1) 2024.10.13
배치 리팩터링  (3) 2024.10.10
'트러블슈팅' 카테고리의 다른 글
  • Spring Batch processor 이야기
  • 연관관계 매핑
  • 관제값 조회 디자인 패턴 적용
  • 그래프 조회 속도 개선
jamin
jamin
  • jamin
    jamin
    jamin
  • 전체
    오늘
    어제
    • 전체 (83)
      • 트러블슈팅 (31)
      • 개념 저장소 (19)
        • coroutine (10)
        • spring reactive (9)
        • network (0)
      • 코딩 테스트 (32)
  • 태그

    그리디 알고리즘
    mirroring mode
    spring reactive
    백준
    BFS
    다이나믹 프로그래밍
    reactive
    경로압축
    그리디
    수학
    instancio
    DP
    spring boot
    백준 23758
    대용량 데이터
    JPA
    error alram
    다익스트라
    cluster mode
    정렬
    코테
    코딩테스트
    log
    dfs
    coroutine
    Kotlin
    sinks
    누적합
    batch
    분리집합
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
jamin
어노테이션 기반 권한 관리
상단으로

티스토리툴바