본문 바로가기

Language/Spring Security

메서드 기반 인가 관리자 - PreAuthorizeAuthorizationManager 외 클래스 구조 이해

728x90
  • 스프링 시큐리티는 메서드 기반의 인증된 사용자 및 특정 권한을 가진 사용자의 자원 접근 허용 여부를 결정하는 인가 관리자 클래스들을 제공
    • PreAuthorizeAuthorizationManager, PostAuthorizeAuthorizationManager, Jsr250AuthorizationManager, SecuredAuthorizationManager
  • 메서드 기반 권한 부여는 내부적으로 AOP 방식에 의해 초기화 설정이 이루어지며 메서드의 호출을 MethodInterceptor가 가로 채어 처리

메서드 인가 처리

@PreAuthorize("hasAuthority('ROLE_USER')")
public List<User> users() {
	System.out.println("users: " + UserRepositiry.findAll());
}
  • user() 메서드 호출인증 객체에서 ROLE_USER 권한을 필요로 함
    • Proxy(MethodInterceptor) : user() 메서드 호출
    • Authentication : 인증 객체
    • GrantedAuthority : ROLE_USER 권한

메서드 권한 부여 초기화 과정

  1. 스프링은 초기화 시 생성되는 전체 빈을 검사하면서 빈이 가진 메소드 중에서 보안이 설정된 메소드가 있는지 탐색
  2. 보안이 설정된 메소드가 있다면 스프링은 그 빈의 프록시 객체(실제 객체가 아님)를 자동으로 생성
    → 기본적으로 Cglib 방식으로 생성
  3. 보안이 설정된 메소드에는 인가 처리 기능을 하는 Advice(MethodInterceptor)를 등록
  4. 스프링은 빈 참조시 실제 빈이 아닌 프록시 빈 객체를 참조하도록 처리
  5. 초기화 과정이 종료
  6. 사용자는 프록시 객체를 통해 메소드를 호출하게 되고 프록시 객체는 Advice가 등록된 메서드가 있다면 호출하여 작동
  7. Advice는 메소드 진입 전(PreAuthorize이기 때문) 인가 처리를 하게 되고 인가 처리가 승인되면 실제 객체의 메소드를 호출하게 되고 인가처리가 거부되면 예외가 발생하고 메소드 진입이 실패

메서드 인터셉터 구조

  • AuthorizationManagerBeforeMethodInterceptor
    • 지정된 AuthorizationManager 를 사용하여 Authentication 이 보안 메서드를 호출 할 수 있는지(PreAuthorize) 여부를 결정하는 MethodInterceptor 구현체
  • AuthorizationManagerAfterMethodInterceptor
    • 지정된 AuthorizationManager 를 사용하여 Authentication 이 보안 메서드의 반환 결과에 접근(PostAuthorize) 할 수 있는지 여부를 결정할 수 있는 구현체
  • PreFilterAuthorizationMethodInterceptor
    • @PreFilter 어노테이션에서 표현식을 평가하여 메소드 인자를 필터링 하는 구현체
  • PostFilterAuthorizationMethodInterceptor
    • @PostFilter 어노테이션에서 표현식을 평가하여 보안 메서드에서 반환된 객체를 필터링 하는 구현체

초기화 과정 구성도

  • PreAuthorizae, Secure, PermitAll은 모두 메소드 실행 전 검사를 하기 때문에 AuthorizationManagerBeforeMethodInterceptor를 사용하지만 내부적으로 사용되는 구현체가 다름

@PreAuthorize 처리 구조 이해

  1. 클라이언트가 user() 메서드 호출
  2. Proxy가 요청을 받아 DefaultAdvisorChainFactory에 class(UserService), method(users)의 정보를 전달
  3. DefaultAdvisorChainFactory 클래스는 users에 선언된 권한 심사(@PreAuthorizae(”hasAuthority(’ROLE_USER’)”))를 할 수 있는 Advice를 반환
  4. Proxy는 Advice(AuthorizationManagerBeforeMethodInterceptor)를 호출
  5. Advice는 내부적으로 가지고 있는 PreAuthorizeAuthorizationManager의 check() 메서드를 실행
  6. PreAuthorizeAuthorizationManager는 권한 설정에 대한 평가를 담당하는 클래스들을 호출 (MethodSecurityExpressionHandler)
  7. 최종적으로 AuthorizationDecision을 반환하여 true일 시 MethodInvocation.proceed()를 호출하여 실제 UserService.users()를 호출 → false일 경우 거부

@PostAuthorize 처리 구조 이해

  1. 클라이언트가 user() 호출
  2. Proxy가 class와 method 정보를 DefaultAdvisorChainFactory에게 전달
  3. Advice(AuthorizationManagerAfterMethodInterceptor)를 반환하고 MethodInvocation.proceed() 하여 UserSerivce.users()를 호출하고 결과를 반환 받음
  4. returnObject(UserService.user()의 반환 객체)를 PostAuthorizeAuthorizationManager에게 전달하여 권한 설정에 대한 평가를 담당하는 클래스 호출 (MethodSecurityExpressionHandler)
    • 스프링 시큐리티는 메서드 기반의 인증된 사용자 및 특정 권한을 가진 사용자의 자원 접근 허용 여부를 결정하는 인가 관리자 클래스들을 제공
      • PreAuthorizeAuthorizationManager, PostAuthorizeAuthorizationManager, Jsr250AuthorizationManager, SecuredAuthorizationManager
    • 메서드 기반 권한 부여는 내부적으로 AOP 방식에 의해 초기화 설정이 이루어지며 메서드의 호출을 MethodInterceptor가 가로 채어 처리
728x90