스프링 시큐리티의 권한
AOP : Aspect Oriented Programming
스프링 전반을 아우르는 여러 철학이 있다. 가장 중요한 철학은 DI(의존성 주입)이다. 개발자가 직접 코딩하지 말고 컨테이너에게 맡기라는 말이다. DI를 통해 약한 상관성(Loosely Coupled)를 설계할 수 있고 모듈화를 완성할 수 있다. 코드를 스파게티로 엮지 말고 관심이 있는 코드를 따로 관리하라는 것이다. 관심사 분리가 가능한 이유는 AOP 기술 덕분이다. AOP는 아래와 같은 개념들로 구성된다.
AOP란
-
Aspect : 공통의 관심사
-
Weaving
- 빈과 빈을 Proxy로 감싸서 연결해주는 작업
- 빈과 빈의 호출 사이에 PointCut을 적용해서 JoinPoint를 판별한 다음 PointCut을 요청한 Advice를 JoinPoint에 적용해줌
-
Pointcut : JoinPoint를 만들어내는 칼
- JoinPoint를 지적해주는 Expression
- annotation 마킹
-
JoinPoint : 관절, 빈과 빈 사이에서 호출이 일어나는 곳
- 메소드 호출
- setter를 통한 멤버 주입
- 생성자 호출
-
Advice : 호출 시 추가로 처리해줄 로직
권한(Authorization)
- SecurityFilterChain 당 한 개의 FilterChainInterceptor를 둘 수 있고, 각 SecurityInterceptor 당 한 개의 AccessDecisionManager를 둘 수 있다. 반면 Method 권한 판정은 Global한 권한 위원회를 둔다. 그래서 GlobalMethodSecurityConfiguration을 통해 AccessDecisionManager를 설정한다.
- 인증이 모든 요청에 대해 공통적으로 처리해야 하는 것인데 반해 권한은 상황에 맞게 처리해야 하는 특징이 있다.
- 그래서 인증을 처리하는 코드는 필터와 어울리고, 권한은 interceptor와 어울려 동작한다. 필터는 servlet container가 제공하는 구조를 스프링이 자체 filterchain을 만들어서 관리하는 방식으로 처리하고 있고, interceptor는 스프링이 빈을 등록하고 프록시 객체를 가지고 엮어주는 과정에서 각 Pointcut에 의해 구분된 JoinPoint에 interceptor가 Advice하는 매커니즘으로 작동한다.
- 필터 위에 상주하는 Interceptor를 FilterSecurityInterceptor라 하고 Method 위에 annotation의 형태로 상주하는 Interceptor를 MethodSecuirtyInterceptor라고 한다. FilterInterceptor는 필터 설정에서 설정하고 MethodInterceptor는 annotation으로 설정한다. @EnableGlobalMethodSecurity를 설정해줘야 MethodSecurityInterceptor가 동작한다.
권한 처리에 관여하는 것들
그런데 권한을 체크하려면 다음과 같은 고민을 해봐야 한다.
-
접근하려고 하는 사람이 어떤 접근 권한을 가지고 있는가?
-
GrantedAuthority
- Role Based
- Scope Based
- User Defined
-
접근하려고 하는 상황에서는 체크해야 할 내용은 무엇인가?
- SecurityMetadataSource, ConfigAttribute
- 정적인 경우와 동적인 경우
- AccessDecisionVoter가 vote 해줌
-
여러가지 판단 결과가 나왔을 때 취합은 어떤 방식으로 할 것인가?
인증과 권한의 구조
-
인증이 AuthenticationFilter를 가지고 Authentication을 발급해주는 관계였다면, 권한은 SecurityInterceptor에서 Access Granted와 Denied를 판정하는 결과를 만들어내는 대응 관계를 가지고 있다.
-
인증이 제공해주는 권한과 각 Interceptor가 위치한 포인트의 조건들(ConfigAttribute)들을 가지고 판정을 내려주는 Voter들에 따라 Granted / Denied가 구분이 된다. 그렇지만 권한은 인증보다 훨씬 상황이 다양하다고 볼 수 있다.
-
AccessDecisionManger는 인터페이스이다. 반드시 Voter를 구현해서 처리해야 할 필요는 없다. Application을 구현한다면 Voter 없이 구현하는 것이 간단할 수 있다.
권한 처리 클래스
참고
- 패스트 캠퍼스 : Java/Spring 웹 개발 마스터 초격차 패키지