본문 바로가기

Language/Spring Security

인가 설정 응용 - RequestMatcherDelegatingAuthorizationManager

728x90
  • RequestMatcherDelegatingAuthorizationManager의 mappings 속성에 직접 RequestMatcherEntry 객체를 생성하고 추가
  • RequestMatcherEntry<T> 클래스의 메서드
    • getEntry() : 요청 패턴에 매핑된 AuthorizationManager 객체를 반환
    • getRequestMatcher() : 요청 패턴을 저장한 RequestMatcher 객체를 반환

적용

  • RequestMatcherDelegatingAuthorizationManager를 감싸는 CustomRequestMatcherDelegatingAuthorizationManager를 구현

 

적용 후 구조

  • 가장 바깥쪽에는 access() API 사용 시 기본으로 생성되기 때문에 위와 같은 구조를 가짐
  • 위와 같은 구조는 좋은 구조가 아니지만 원리를 이해하기 위해 위처럼 설정

SecurityConfig.java

@Bean
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
	return http.authorizeHttpRequests(auth -> auth.anyRequest().access(authorizationManager(null))).build();
}
@Bean
public AuthorizationManager<RequestAuthorizationContext> authorizationManager(HandlerMappingIntrospector introspector){
	List<RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>>> mappings = new ArrayList<>();
	
	RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>> requestMatcherEntry1 =
		new RequestMatcherEntry<>(new MvcRequestMatcher(introspector, "/user"), AuthorityAuthorizationManager.hasAuthority("ROLE_USER"));

	RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>> requestMatcherEntry2 =
		new RequestMatcherEntry<>(new MvcRequestMatcher(introspector, "/admin"), AuthorityAuthorizationManager.hasRole("ADMIN"));
	
	RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>> requestMatcherEntry3 =
		new RequestMatcherEntry<>(AnyRequestMatcher.INSTANCE, new AuthenticatedAuthorizationManager<>());
	
	mappings.add(requestMatcherEntry1);
	mappings.add(requestMatcherEntry2);
	mappings.add(requestMatcherEntry3);
	
	return new CustomRequestMatcherDelegatingAuthorizationManager(mappings);
}
  • requestMatcherEntry1 ⇒ /user에 접근하기 위해서는 ROLE_USER의 권한을 가져야 함
  • requestMatcherEntry2 ⇒ /admin에 접근하기 위해서는 ROLE_ADMIN의 권한을 가져야 함
  • requestMatcherEntry3 ⇒ 그 외의 모든 접근(AnyRequestMatcher.INSTANCE)에는 인증을 해야 함

CustomRequestMatcherDelegatingAuthorizationManager

public class CustomRequestMatcherDelegatingAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
	private final RequestMatcherDelegatingAuthorizationManager manager;
	
	public CustomRequestMatcherDelegatingAuthorizationManager(List<RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>>> mappings) {
		Assert.notEmpty(mappings, "mappings cannot be empty");
		manager = RequestMatcherDelegatingAuthorizationManager.builder().mappings(maps -> maps.addAll(mappings)).build();
	}
	
	@Override
	public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
		return manager.check(authentication,object.getRequest());
	}
	
	@Override
	public void verify(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
		AuthorizationManager.super.verify(authentication, object);
	}
}
  • 요청에 대한 권한 검사를 RequestMatcherDelegatingAuthorizationManager 객체가 수행하도록 함
  • RequestMatcherDelegatingAuthorizationManager → CustomRequestMatcherDelegatingAuthorizationManager 
    → RequestMatcherDelegatingAuthorizationManager 구조는 좋은 구조가 아니기 때문에 개선이 필요
728x90