인증(Authentication) section에서 전에 모든 Authentication 구현체들을 GrantedAuthority 객체의 하나의 리스트로 저장할 수 있는지 이야기했다.
띠용! 사실 필자는 이게 공부한다고 봤지만 기억이 안나서 다시 찾아보았다...
https://tech-monster.tistory.com/203
어머나 세상에... 정말이잖아...? 내가 이걸 공부했엇구나 ㅠㅠㅠ
객체의 Collection을 제공한다고 한것이 하나의 리스트로 저장할 수 있다는 것과 동의어인것 같다.
이것을 다시 보면서 다시 읽어보도록 하자.
이것들은 principal(본인, 사용자)에게 허가받아온 권한들을 나타낸다.
GrantedAuthority객체의 리스트가 곧 허가받아온 권한들을 나타낸다고 한다.
GrantedAuthority 객체들은 AuthenticationManger에 의해 Authentication 객체 안에 삽입되고, 나중에 권한 결정을 내릴 때 AuthorizationManager에 의해 읽힌다.
GrantedAuthority는 오직 하나의 메소드만 가지고 있다.(띠용?)
String getAuthority();
이 메소드는 AuthorizationManager들이 GrantedAuthority의 정확한 String representation을 얻도록 해준다. String 으로 representation을 반환함으로서, GrantedAuthority는 대부분 AuthorizationManager나 AccessDecisionManager에 의해 쉽게 읽힐 수 있다.
만약 GrantedAuthority가 정확하게 String으로 나타내지지 않는다면, GrantedAuthority는 복잡하다고 여겨질 것이고 getAuthority는 반드시 null을 return한다.
편의성을 위해서 getAuthority()는 GrantedAuthroity(이걸 해석해보면 허가받은 권한 혹은 허가받은 권한의 이름 정도? 로 보면 될 것 같다.)를 string의 형식으로 무조건 반환해서 읽도록 하는 것 같다.
Spring Security는 하나의 GrantedAuthority 구현체인 SimpleGrantedAuthority를 제공한다. 이것은 어떤 특정한 String이GrantedAuthority로 변환되도록 한다. 시큐리티의 구조에 포함된모든 AuthenticationProvider들은 Authentication 객체를 공유하기 위해 SimpleGrantedAuthority를 사용한다.
2. 선 호출 관리(Pre-Invocation Handling)
Spring Security는 method invocation이나 web request 같은 객체들을 보호하기 위해 접근을 제어하는 interceptor들을 제공한다.
호출이 처리되도록 허가됫는지 안됬던지에 대한 선 호출(pre-invocation) 결정(decision)은 AccessDecisionManager에 의해 처리된다.
3. The AuthorizationManager
AuthorizationManager는 AccessDecisionManager와 AccessDecisionVoter를 둘 다 대체한다.
AccesssDecisionManager 혹은 AccessDecisionVoter를 customize한 어플리케이션은 AuthoizationManager를 사용해서 변경하는것을 권장한다.
AuthenticationManager들은 AuthorizationFilter에 의해 호출되고, 최종 접근 제어 결정을 내리는데 책임이 있다.
특히, 안전한(secure) object를 넘기는 것은 이러한 인자들이 관찰된 실제 secure 객체 호출을 포함하는것을 가능하게 한다.
예를 들어, secure object가 MethodInvocation이라고 가정하자.
모든 Customer 인자에게 MethodInvocation을 요청하는 것은 간단할 것이며 , principal(사용자)가 그 고객으로 역할을 하도록 허락을 받는것을 확실히 하려고 AuthorizationManager에서 security logic의 몇개를 구현할 수 있다.
verify 메소드는 check을 호출하고, 연속적으로 부정적인 AuthorizationDecision의 경우에 AccessDeninedException을 던진다.
이러한 접근을 가지고, AuthroizationManager 구현체들의 구성은 인가 결정에서 고를 수 있다.(poll - 선택될 수 있다고 봐도 무방 : 여기서 여러개의 선택지가 있어서 원하는 것을 선택한다는 것에서 poll이라는 단어를 선택한 것 같다.)
5. AuthorityAuthroizationManager
Spring Security에서 제공되는 가장 흔한 AuthorizationManager는 AuthorityAuthorizationManager다.
(이름 자체가 인가 중 권한에 대한 처리를 담당하는 것 같다.)
현재 Authenticiation에서 찾고 있는 주어진 권한 세트를 설정한다.
Authentication이 어떠한 설정된 권한을 포함한다면 positive AuthroizationDecision을 반환한다.
그렇지 않으면, negative를 반환한다.
6. AuthentizatedAuthorizationManger
다른 매니저는 AuthenticationManager이다. 이것은 익명사용자, 완전이 인증받은 사용자, 그리고 remember-me로 인증된 사용자들을 구별하기 위해 사용된다.
7. Custom Authorization Managers
명확하게, custom AuthorizationgManager를 구현할 수 있고, 원하는 접근 제어 로직을 넣을 수 있다.
당신 application에서 이것은 구체적일것수 있고 혹은 몇몇 security 관리 로직을 구현할 수 있다.
예를 들어, Open Policy Agent를 요청하거나 당신 자신의 인가 데이터베이스에 요청을 할 수있는 구현체를 생성할 수 있다.
8. Adapting AccessDecisionManager and AccessDecisionVoters
이전의 AuthroizationManager에서, Spring Security는 AccessDecisionManager와 AccessDecisionVoter를 공개했다.(publish)
몇몇 경우에, 더 오래된 application으로 migrating하는 것 처럼 AccessDecisionManager와 AccessDecisionVoter를 호출하는 AuthorizationManger를 도입하는건 바람직할 수 있다.
기존에 존재하는 AccessDecisionManager를 부르기 위해, 당신은 다음처럼 할 수 있다.
Example 1. Adapting an AccessDecisionManager
@Component
public class AccessDecisionManagerAuthorizationManagerAdapter implements AuthorizationManager {
private final AccessDecisionManager accessDecisionManager;
private final SecurityMetadataSource securityMetadataSource;
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {
try {
Collection<ConfigAttributes> attributes = this.securityMetadataSource.getAttributes(object);
this.accessDecisionManager.decide(authentication.get(), object, attributes);
return new AuthorizationDecision(true);
} catch (AccessDeniedException ex) {
return new AuthorizationDecision(false);
}
}
@Override
public void verify(Supplier<Authentication> authentication, Object object) {
Collection<ConfigAttributes> attributes = this.securityMetadataSource.getAttributes(object);
this.accessDecisionManager.decide(authentication.get(), object, attributes);
}
}
그리고 나서, Security FilterChain에 등록하라.
혹은, AccessDecisionVoter를 다음처럼 호출 할 수 있다.
@Component
public class AccessDecisionVoterAuthorizationManagerAdapter implements AuthorizationManager {
private final AccessDecisionVoter accessDecisionVoter;
private final SecurityMetadataSource securityMetadataSource;
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {
Collection<ConfigAttributes> attributes = this.securityMetadataSource.getAttributes(object);
int decision = this.accessDecisionVoter.vote(authentication.get(), object, attributes);
switch (decision) {
case ACCESS_GRANTED:
return new AuthorizationDecision(true);
case ACCESS_DENIED:
return new AuthorizationDecision(false);
}
return null;
}
}
그리고 나서, Security FilterChain에 등록하라.
9. Hierarchical Roles
application에서 특정한 역할이 자동적으로 다른 역할을 포함하는것은 흔한 요구사항이다.
예를 들어, admin과 user 역할의 개념을 가진 application에서, 당신은 admin이 일반 유저가 할 수 있는 모든것을 할 수 있으도록 하고 싶을 수 있다.
이를 위해서, 모든 admin 사용자가 user 역할을 부여받도록 할 수 있다.
대안으로, 또한 admin role들이 user role을 포함하도록 제한을 걸 수 있다.
이것은 applicatiojn에서 역할이 많이 다양하다면 복잡할 수 있다.
role-hierarchy는 역할들이 다른 역할을 포함할 수 있도록 한다. Spring Security의 RoleVoter를 상속한 RoleHierarchyVoter는 RoleHierarchy로 설정되는데, RoleHierarchy는 사용자가 할당받은 모든 다을 수 있는 권한들을 포함하고 있다.
이 접근을 사용하는 일련의 AccessDecisionVoter의 구현체들은 인가 결정에서 투표받는다. AccessDecisionManager는 그리고 할당받은 투표에 따라서 AccessDeniedException을 던질지 말지 결정한다.(던질까말까 던질까말까~ 던던던던~)
Spring Security의 다른 많은 부분들처럼, AfterInvocationManager가 하나의 concrete 구현체인 AfterInvocationProviderManager를 가진다. AfterInvocationProviderManager는 AfterInvocationProvider들의 리스트를 투표한다.
각각의 AfterInvocationProvider는 반환 객체를 수정하거나 AccessDeniedException을 던지는 것을 허가받는다.
실제 다수의 provider들이 object를 수정할 수 있고, 그 결과 이전의 provider가 그 리스트의 다음으로 넘겨진다.
이번 시간에 인가 구조에 대해서 알아보았다. 이맘 때 쯤 되니 기존에 알아보았던 Authentication 관련 설명들이 기억이 잘 안았다.
다시 봐야한는것은 맞겠지만, 인가에 대한 설명을 보면서도 인증 관련 설명이 중간 중간에 있으니 큰 흐름을 보는것이 좋을 것 같다는 생각이 들었다.