본문 바로가기

Language/Spring Security

인가 이벤트 - Authorization Events

728x90
  • Spring Security는 권한 부여 이벤트 처리를 지원하며 권한이 부여되거나 거부된 경우에 발생하는 이벤트를 수신 가능
  • 이벤트를 수신하려면 ApplicationEventPublisher 를 사용하거나 시큐리티에서 제공하는 AuthorizationEventPublisher를 사용해서 발행해야 함
  • AuthorizationEventPublisher의 구현체로 SpringAuthorizationEventPublisher가 제공

 

이벤트 발행 방법

  • ApplicationEventPublisher.publishEvent(ApplicationEvent)
  • AuthorizationEventPublisher.publishAuthorizationEvent(Supplier<Authentication>, T, AuthorizationDecision)

 

이벤트 수신 방법

@Component
public class AuthorizationEvents {
	// 접근 거부 시 발생 하는 이벤트
	@EventListener
	public void onAuthorization(AuthorizationDeniedEvent failure){…}
	
	// 접근 허용 시 발생 하는 이벤트
	@EventListener
	public void onAuthorization(AuthorizationGrantedEvent success){…}
}

 

인가 이벤트 발행 & 수신

  • 인가 이벤트를 발행 하기 위해서는 SpringAuthorizationEventPublisher를 빈으로 정의
@Bean
public AuthorizationEventPublisher authorizationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
	// 인가가 실패했을 경우에만 발행
	return new SpringAuthorizationEventPublisher(applicationEventPublisher);
}
@Component
public class AuthorizationEvents {
	@EventListener
	public void onAuthorization(AuthorizationEvent event){
		System.out.println("failure = " + event.getAuthentication().get().getAuthorities());
	}
	
	@EventListener
	public void onAuthorization(AuthorizationDeniedEvent failure){
		System.out.println("failure = " + failure.getAuthentication().get().getAuthorities());
	}
	
	@EventListener
	public void onAuthorization(AuthorizationGrantedEvent success){
		System.out.println("success = " + success.getAuthentication().get().getAuthorities());
}

 

커스텀 AuthorizationEventPublisher 구현

@Component
public class MyAuthorizationEventPublisher implements AuthorizationEventPublisher {
	@Override
	public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication,T object, AuthorizationDecision decision) {
		if (decision == null) return;
		
		if (!decision.isGranted()) { // 인가 실패 이벤트를 발행
			this.delegate.publishAuthorizationEvent(authentication, object, decision);
			return;
		}
		// 인가 성공 시 아래 코드 실행
		if (shouldThisEventBePublished(decision)) // Authentication 의 권한이 ROLE_ADMIN 인 경우 인가 성공 이벤트를 발행
			this.publisher.publishEvent(new AuthorizationGrantedEvent(authentication, object, decision););
	}
	
	private boolean shouldThisEventBePublished(AuthorizationDecision decision) {
		if (!(decision instanceof AuthorityAuthorizationDecision)) return false;
		Collection<GrantedAuthority> authorities = ((AuthorityAuthorizationDecision) decision).getAuthorities();
		for (GrantedAuthority authority : authorities) {
			if ("ROLE_ADMIN".equals(authority.getAuthority())) return true;
				return false;
	}
}
728x90