12.1. Domain Object Security (ACLs)
12.1.1. Overview
복잡한 애플리케이션들은 종종 웹 요청이나 메서드 실행 레벨에서 끝나지 않는 복잡한 접근권한을 정의할 필요가 있다. 대신 security decision은 누가(Authentication), 어디에서(MethodInvocation), 무엇을(SomeDomainObject) 원하는지를 함께 보고 결정될 필요가 있다.
애견 클리닉 애플리케이션을 디자인한다고 상상해보자. 직원과 고객이라는 두 그룹이 필요할 것이다. 스태프는 모든 데이터에 접근 가능해야 할 것이고, 손님은 자기 자신의 고객 레코드에 대해서만 접근 가능해야 한다. 상황을 좀 더 재미있게 만들어서, 고객들은 애견 유치원 멘토나 지역 포니 클럽 장의 고객 레코드에 대해서도 접근 가능하다고 해보자. Spring Security에는 이를 구현할수있는 몇가지 방식이 있다.
- 보안을 집행하는 비지니스 메서드를 구현한다.
Customer
도메인 객체 인스턴스에 자신이 엑세스 권한을 가지고 있는 유저 목록을 컬렉션을 도입할수 있다.SecurityContextHolder.getContext().getAuthentication()
을 사용하여Authentication
객체에 접근 할 수 있다. - Authentication에 저장된
GrantedAuthority[]
에 기반해 보안을 집행하는AccessDecisionVoter
를 구현한다. 이것은 당신의AuthenticationManager
로 하여금 권한이 있는 principal들을 표현하는 Customer 도메인 객체를GrantedAuthority[]
로 갖는 Authentication을 생성하도록 하는것을 의미 할 것이다. AccessDecisionVoter
를 작성하고 타겟 Custom 도메인 객체를 열도록 한다. 이것은 voter들로 하여금 Customer 객체를 획득하는 DAO에 엑세스 하도록 하는것을 의미 할 것이다.
각각의 방법들은 완전히 적절하다. 그러나 첫번째는 권한 체킹과 비지니스 코드를 엮게 한다. 이를 포함한 주요 문제점들은 유닛 테스팅을 어렵게 하고 Customer 인가 로직을 다른데서 재활용 하기 어렵게 만든다는 것이다. Authentication 객체로부터 GrantedAuthority[]
를 획득하는것은 괜찮지만 다수의 Customer로 확장할순 없다. 만약 5천명의 Customer로 확장되면 메모리 소비 및 연산시간이 필요해진다. 외부 코드에서 Customer를 직접 여는 방식은 아마 셋중 최선이 될 것이다. 관심사가 분리되며, 메모리와 CPU 사이클 낭비를 막을 수 있지만, 여전히 Customer 객체를 얻기 위해선 AccessDecisionVoter DAO 를 호출하기 때문에(비지니스 로직에서도 호출할텐데!) 비효율 적인 상태다. 하나의 메서드 실행에 2회의 접근은 명백히 지양해야 할 일이다. 추가적으로, 위에 언급된 세 방법 모두 ACL(Access Control List) 저장과 비지니스 로직을 처음부터 작성해야 한다.
다행히도, 대안이 있다.
12.1.2 Key Concepts
Spring Security의 ACL 서비스는 spring-security-acl-xxx.jar
에 실려 있다. 모든 도메인 객체 인스턴스는 고유한 ACL이 있고, 누가 해당 도메인 객체에 접근 허용되는지 거부되는지에 대한 ACL 레코드 상세를 가지고 잇다. 이것을 염두에 두고, Spring Security는 ACL와 관련된 세개의 기능을 제공한다.
.. 생략