티스토리 뷰

728x90
반응형

지난 글까지 스프링 시큐리티와 그 안에서 인증이 이뤄지는 과정을 살폈다.

 

2022.09.21 - [Development/Spring] - [Spring]Spring Security

2022.09.22 - [Development/Spring] - [Spring]Spring Security - 인증(Authentication) 구조

 

[Spring]Spring Security - 인증(Authentication) 구조

지난 글에서 스프링 시큐리티의 구조와 작업 흐름을 간략하게 살펴보았다. 2022.09.21 - [Development/Spring] - [Spring]Spring Security [Spring]Spring Security 스프링 시큐리티는 2003년 발표된 인증(Authent..

gnidinger.tistory.com

이번 글에선 인증에 이어 권한 부여의 흐름에 대해 살핀다.

Spring Security: Authorization Architecture

 

권한 부여(Authorization, 인가)인증을 통과한 사용자에게 Role에 따라 특정 권한(Authority)을 부여하는 절차이다.

 

여기서 권한이란 사용하는 앱의 특정 리소스에 접근할 수 있는 권한을 말하며,

 

사용자에 따라 권한을 제어하는 행위를 따로 접근 제어(Access Control)라 부르기도 한다.

 

또한 권한 부여는 당연하게도 반드시 인증과정 이후에 수행되어야 하는데,

 

지난 글에서 알아본 인증 과정을 통과한 사용자에게 어떤 방식으로 권한이 부여되는지 알아보자.

 

먼저 대략적인 그림을 보면 아래와 같다.

 

계속해서 단계별로 코드를 열어보며 진행해보자.

 

AuthorizationFilter

 

스프링 시큐리티의 필터 체인에서 권한 부여를 담당하는 필터 클래스이다.

 

URL을 통해 사용자의 접근을 제한하는 기능을 하며, 스프링 시큐리티 5.5부터 인터셉터를 대체하고 있다.

 

스프링 시큐리티 5.5 이전까지는 FilterSecurityInterceptor 클래스를 통해 복잡한 권한 부여 과정을 거쳐야 했지만

 

5.5 버전에서 도입된 AuthorizationFilter를 통해 AuthorizationManager API를 이용해서

 

간단한 권한 부여 처리를 할 수 있게 되었다.

 

 

필터는 먼저 SecurityContextHolder로부터 인증을 획득한다.

 

이어서 권한 부여 처리 후 HttpServletRequest와 함께 인증을 전송하는 역할을 하는데,

 

이 역할은 다음 컴포넌트인 AuthorizationManager 인터페이스를 DI 받음으로써 가능해진다.

 

코드를 살펴보자.

public class AuthorizationFilter extends OncePerRequestFilter {

    private final AuthorizationManager<HttpServletRequest> authorizationManager;
  ...

    public AuthorizationFilter(AuthorizationManager<HttpServletRequest> authorizationManager) { // DI
        Assert.notNull(authorizationManager, "authorizationManager cannot be null");
        this.authorizationManager = authorizationManager;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

      // AuthorizationManager의 check() 메서드 호출 및 권한 부여 여부 확인
        AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, request);
        ...
        filterChain.doFilter(request, response);
    }
  ...
}

AuthorizationManager를 주입받아 check() 메서드를 사용하는 것을 볼 수 있다.

 

참고로 check() 메서드는 AuthorizationManager의 구현 클래스에 따라 로직이 다른데,

 

URL을 기반으로 한 권한 부여 처리는 다음에 볼 RequestMatcherDelegatingAuthorizationManager를 사용한다.

 

AuthorizationManager

 

권한 부여 처리를 총괄하는 관리자 역할을 한다.

@FunctionalInterface
public interface AuthorizationManager<T> {
  ...
	@Nullable
	AuthorizationDecision check(Supplier<Authentication> authentication, T object);
}

권한 부여 여부를 확인하는 check() 메서드가 정의된 것을 확인할 수 있다.

 

RequestMatcherDelegatingAuthorizationManager

 

AuthorizationManager의 구현체 중 하나이며, 직접 권한 부여 처리를 하지 않고

 

RequestMatcher를 통해 매치되는 AuthorizationManager에게 권한 부여 처리를 위임한다.

 

계속해서 매치되는 Authorization 구현 클래스가 있다면 그 구현 클래스가 사용자의 권한을 체크하며,

 

적절한 권한이라면 다음 단계를, 그렇지 않다면 예외를 표시한다.

public final class RequestMatcherDelegatingAuthorizationManager implements AuthorizationManager<HttpServletRequest> {
  ...
    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, HttpServletRequest request) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace(LogMessage.format("Authorizing %s", request));
        }

        // 반복문을 돌며 RequestMatcherEntry 정보 획득
        for (RequestMatcherEntry<AuthorizationManager<RequestAuthorizationContext>> mapping : this.mappings) {

            RequestMatcher matcher = mapping.getRequestMatcher(); // 정보를 바탕으로 RequestMatcher 객체 획득
            MatchResult matchResult = matcher.matcher(request);
            if (matchResult.isMatch()) {   // 매치되면 AuthorizationManager 객체를 얻어 사용자의 권한 체크
                AuthorizationManager<RequestAuthorizationContext> manager = mapping.getEntry();
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace(LogMessage.format("Checking authorization on %s using %s", request, manager));
                }
                return manager.check(authentication,
                        new RequestAuthorizationContext(request, matchResult.getVariables()));
            }
        }
        this.logger.trace("Abstaining since did not find matching RequestMatcher");
        return null;
    }
}

추가로 여기서 RequestMatcher 객체는 SecurityConfiguration에서 메서드 체인 정보를 기반으로 생성된다.

 

Summary

 

  • 권한 부여(Authorization, 인가) 인증을 통과한 사용자에게 Role에 따라 특정 권한(Authority)을 부여하는 절차이다.
  • 권한이란 사용하는 앱의 특정 리소스에 접근할 수 있는 권한을 말한다.
  • 스프링 시큐리티 5.5 버전에서 도입된 AuthorizationFilter 덕분에 간단한 권한 부여 처리를 할 수 있게 되었다.
  • AuthorizationFilter는 URL을 통해 사용자의 접근을 제한하는 기능을 한다.
  • RequestMatcherDelegatingAuthorizationManager는 AuthorizationManager의 구현체 중 하나이다.
  • RequestMatcher를 통해 매치되는 AuthorizationManager에게 권한 부여 처리를 위임한다.
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함