Programming/Spring

[Spring Security] 권한 부여 처리 흐름

Smile :DK 2023. 7. 17. 21:29
더보기

Authorization(인가, 권한 부여)

  • 인증(Authentication) 과정이 정상적으로 수행된 사용자에게 하나 이상의 권한(Authority)을 부여하여 특정 애플리케이션의 특정 자원(Resource)에 접근할 수 있게 허가 하는 과정
  • Authorization은 반드시 인증 과정 이후 수행되어야 하며 권한은 일반적으로 역할(Role)의 형태로 부여 된다.

Spring Security 권한 부여 처리 흐름

Spring Security 컴포넌트로 보는 권한 부여 처리 흐름

  1. AuthorizationFilter는 SecurityContextHolder로부터 Authentication을 획득한다.
  2. SecurityContextHolder로부터 획득한 Suppier<Authentication>과 HttpServletRequest를 AuthorizationManager에게 전달한다.
  3. AuthorizationManager의 구현체인 RequestMatcherDelegatingAuthorizationManager 내부에서 매치되는 AuthorizationManager 구현 클래스가 있다면 AuthorizationManager 구현 클래스가 사용자의 권한을 체크
    1. 적절한 권한 ⇒ 다음 요청 프로세스를 이어감
    2. 적절하지 않은 권한 ⇒ AccessDeniedException이 throw 되고 ExceptionTranslationFilter가 AccessDeniedException을 처리

 

  • AuthorizationManager(인터페이스) / RequestMatcherDelegatingAuthorizationManager(구현체)
  • RequestMatcherDelegatingAuthorizationManager는 RequestMatcher 평가식을 기반으로 해당 평가식에 매치되는 AuthorizationMagager에게 권한 부여 처리를 위임하는 역할
  • RequestMatcherDelegatingAuthorizationManager가 직접 권한 부여 처리 하는 것이 아닌 RequestMatcher를 통해 매치되는 AuthorizationManager 구현 클래스에게 위임만 함

 

 

AuthorizationFilter

URL을 통해 사용자의 접근(Access)을 제한하는 권한 부여 필터이며 SpringSecurity 5.5 이전 버전의 FilterSecurityInterCeptor를 대체한다.

  • AuthorizationFilter 객체가 생성될 때, AuthorizationManager를 의존성 주입(DI) 받는다.
    • DI 받은 AuthorizationManager를 통해 권한 부여 처리를 진행
  • DI받은 AuthorizationManager의 check() 메서드를 호출하여 적절한 권한 부여 여부를 체크한다.
    • AuthorizationManager의 check() 메서드는 구현 클래스에 따라 권한 체크 로직이 다르다
    • URI 기반으로 권한 부여 처리를 하는 AuthorizationFilter는 AuthorizationManager의 구현 클래스로 RequestMatcherDelegatingAuthorizationManager를 사용한다.

 

RequestMatcherDelegatingAuthorizationManager

  • check() 메서드 내부에서 루프를 돌면서 RequestMatcherEntry 정보를 얻은 후 RequestMatcher 객체를 얻음
  • Matcher.isMatch()가 true이면 AuthorizationManager 객체를 얻은 뒤 사용자의 권한을 체크

✔️ 여기서 RequestMatcher는 SecurityConfig에서 .antMatcher(”/orders/**).hasRole(”ADMIN”)와 같은 메서드 체인 정보를 기반으로 생성된다.

 

 

접근 제어 표현식

Spring Security 에서 웹 및 메서드 보안을 위해 표현식(Spring EL,Spring Expression Language)을 사용할 수 있다.

표현식 설명
hasRole(Stirng role) - 현재 보안 주체(principal)가 지정된 역할을 갖고 있는지 여부를 확인하고 가지고 있다면 true를 리턴한다.- hasRole(’admin’)처럼 파라미터로 넘긴 role이 ROLE_ 로 시작하지 않으면 기본적으로 추가한다.(DefaultWebSecurityExpressionHandler의 defaultRolePrefix를 수정하면 커스텀할 수 있다.)
hasAnyRole(String… roles) - 현재 보안 주체가 지정한 역할 중 1개라도 가지고 있으면 true를 리턴한다.(문자열 리스트를 콤마로 구분해서 전달한다.)- ex) hasAnyRole(’admin’, ‘user’)
hasAuthority(String authority) - 현재 보안 주체가 지정한 권한을 갖고 있는지 여부를 확인하고 가지고 있다면 true를 리턴한다.- ex) hasAuthority(’read’)
hasAnyAuthority(String… authorities) - 현재 보안 주체가 지정한 권한 중 하나라도 있으면 true를 리턴한다.- ex) hasAnyAuthority(’read’, ‘write’)
principal - 현재 사용자를 나타내는 principal 객체에 직접 접근할 수 있다.
authentication - SecurityContext로 조회할 수 있는 현재 Authentication 객체에 직접 접근할 수 있다.
permitAll - 항상 true로 평가한다.
denyAll - 항상 false로 평가한다.
isAnonymous() - 현재 보안 주체가 익명 사용자면 true를 리턴한다.
isRememberMe() - 현재 보안 주체가 remember-me 사용자면 true를 리턴한다.
isAuthenticated() - 사용자가 익명이 아닌 경우 true를 리턴한다.
isFullyAuthenticated() - 사용자가 익명 사용자나 remember-me 사용자가 아니면 true를 리턴한다.
hasPermission(Object target, Object permission) - 사용자가 target에 해당 permission 권한이 있으면 true를 리턴한다.ex) hasPermission(domainObject, ‘read’)
hasPermission(Object targetId, String targetType, Object permission) - 사용자가 target에 해당 permission 권한이 있으면 true를 리턴한다.ex) hasPermission(1, ‘com.example.domain.Message’, ‘read’)

 


Ref.

https://docs.spring.io/spring-security/reference/5.7-SNAPSHOT/servlet/authorization/expression-based.html