ajax로 파일 업로드 한 후에 리절트 <pre>로 쌓여 있을 때.
이제 스프링 배치 살펴 보기.
화이팅 ㅋㅋ
afterInvocationManager
Customer
instance is retrieved and passed to the AclEntryAfterInvocationProvider
. If the authenticated object does not have the permission to read it, then the provider will throw AccessDeniesException
.http://www.denksoft.com/wordpress/web-development/acl-spring-security-tutorial/
참고 하고 있는 블로그에 있는 내용인데.. 뭔말이야 @_@;;
일단 오브젝트를 겟 한 다음에 권한을 체크 한다는 내용 같다.
그게 무슨말이야.!!!
그전 메소드 시큐리티에서는 오브젝트를 get 하기 전에, 즉 쿼리를 날리기 전에 보안 검사를 하고 있는데,
이것은 쿼리를 실행 한 후 오브젝트를 get 한 후에 이 오브젝트들을 하나 하나 보안 검사를 해서, 보안검사에 통과할 경우 오브젝트들을 보여준다.
오우 좋은데 @_@
그러니까 검색 한 다음에 검색 결과에서 필터링을 할 수 있다는 말!!
그럼 요곳들을 어떻게 쓰느냐.. 일단 아래 설정 처럼 설정 파일을 정의 해 주고.
<sec:after-invocation-provider ref="afterAclCollectionRead"/>
<sec:after-invocation-provider ref="afterAclRead"/>
</sec:global-method-security>
그런 다음에 보안 설정을 할 메서드에 @Secured를 설정 해 주면 된다.
public ArrayList<AclBbs> getList( PagingUtil pagingUtil) {
HashMap<String, Integer> params = new HashMap<String, Integer>();
params.put( PagingUtil.START, pagingUtil.getStart());
params.put( PagingUtil.LIMIT, pagingUtil.getLimit());
params.put( PagingUtil.TOTALCOUNT, pagingUtil.getTotalCount());
return aclBbsDAO.getList( params);
}
이렇게 해서
스프링 시큐리티는 대충 내맘대로 정리 완료??
도메인 acl을 적용해 보자
집에가서 소스 코드 업로드 및 수정 보완 할 것.
기본적인 구성은 http://starplatina.tistory.com/entry/Spring-Security-ACL-Example
여기 링크의 url 을 참고로 소스를 재구성 하였삼.
스프링 도메인 ACLS
- Security 부분이 다른 비즈니스 로직과 독립적으로 운용된다.(도메인 클래스에 따로 ACL 및 보안 관련된 값들이 없고, 별도 테이블에서 관리)
- Affirmative(긍정적인), Consensus(합의에 의한), Unanimous(만장일치의) 권한 체크를 한다. Voter라는 클래스가 투표를 하게 되는데 여기서 긍적적인 표가 한개라도 있으면, 긍정 중립 부정 표를 비교 해서 긍정 표가 있으면, 모두 긍정으로 투표하였을 경우
- accessControllist라는 jsp tag로 권한에 따라서 뷰를 조작 할 수 있다.
- 권한 관리를 위한 테이블이 추가 된다(acl 관련 테이블 4개, 기타 시큐리티 권한 관련 클래스 2~3개)
- 도메인 클래스에 대한 acl 작성시 aop를 사용해서 권한을 부여하는 작업을 해야 한다.
도메인 ACL의 경우 물론 스프링 시큐리티에 대한 이해가 필요 합니다.
(url 보안, 메서드 보안(롤베이스, acl 베이스))
그럼 간단하게 acl을 적용하는 케이스를 보면서 이에 대해서 코드를 구성해나가는 방법으로 알아 보도록 하겠습니다.
일단 어떤 도메인 오브젝트가 있다고 보고 이에 대한 읽기 권한에 대해서 제어를 할 경우.
보통 서비스 클래스의 메서드에 작업을 하게 됩니다.
@Secured({"ROLE_USER", "ACL_OBJECT_READ"})
public Object getObj( String id) {
return (AclBbs)aclBbsDAO.getBbs( id);
}
@Security("USER_ROLE")은 스프링 시큐리티에서 지원하는 롤 베이스 메서드 보안입니다.
getObj()라는 메서드를 호출 할 때, 이 메서드를 호출 하는 사용자가 "USER_ROLE"이라는 권한이 있는지 확인하여 권한이 있을 경우에만 메서드를 실행 할 수 있도록 합니다.
@Security({"USER_ROLE", "ACL_OBJECT_READ"}) 굵게 표시한 "ACL_OBJECT_READ" 이 부분이 바로 ACL 권한을 체크하는 부분입니다.
이 경우에는 조회 할려는 도메인 오브젝트에 대한 사용자의 권한(읽기)이 존재 할 경우에만 메서드를 실행 합니다.
그럼 위 메서드 보안이 동작 하도록 하기 위해서 작업해야할 흐름들을 알아 보도록 하겠습니다.
1. 도메인 오브젝트를 작성 할 때(insert 할때), ACL 권한과 관련된 작업들을 함께 처리해 주어야 한다.
-> 오브젝트에 대한 권한 부여를 해주어야 한다.
2. 시큐리티 설정을 통해서 오브젝트를 호출 할 때, 메서드 보안을 통해 ACL 권한 체크를 하도록 처리 한다.
-> 권한체크 방법(긍정적인, 합의에 의한, 만장일치)에 따라 권한을 체크 해 주어야한다.
기본적으로 위 두가지 작업을 해 주게 되면 보안 작업이 완료 됩니다.
ACL 권한 부여의 경우 서비스 클래스에서 insert 작업이 일어날 경우 작업을 진행하면 됩니다.
insert 메서드 내부에 권한부여 작업을 호출할 수도 있지만, 이렇게 하면 비즈니스로직과 관련없는 로직이 들어가므로 AOP를 적용하여 권한부여 작업을 진행 하도록 합니다.
시큐리티 UML
위 UML에서 AclSecurityUtil은 Acl 오브젝트에 대한 권한 부여를 하는 메서드(addPermission, deletePermission)를 가진 인터페이스 입니다. SecurityService는 AOP를 사용해서 실제 권한 부여 작업을 하는 인터페이스 입니다. SecurityService에서 setPermissions를 통해 AclSecurityUtil의 addPermission을 호출하여 권한을 부여 합니다.
위와 같은 방법으로 권한 부여에 관한 로직을 작성 한 후, XML 설정을 통해서 이를 동작하도록 해 주어야 합니다.
XML 설정
XML 설정은 권한 체크 방법을 정의 하고, 체크할 권한에 대한 정의, ACL 권한 부여에 필요한 bean 정의 를 하게 됩니다.
일단 가장 먼저 해야할 일이 메서드 시큐리티에 대한 access-decision-manager를 설정 해야 합니다.
secured-annotations="enabled" access-decision-manager-ref="businessAccessDecisionManager" >
</sec:global-method-security>
<bean id="businessAccessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<property name="allowIfAllAbstainDecisions" value="true" />
<property name="decisionVoters">
<util:list>
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter" />
<ref local="aclObjectReadVoter" />
<ref local="aclObjectWriteVoter" />
</util:list>
</property>
</bean>
위의 설정을 보면 access-decision-manager로 businessAccessDecisionManager를 참조 하도록 하고, businessAccessDecisionManager에서는 UnanimouseBased(만장일치) 방식으로 권한 체크를 하도록 하고 있습니다. 만약 다른 방법으로 사용하고 싶다면 클래스를 AffirmativeBased나 ConsensusBased로 정의 하면 각각의 방식으로 권한 체크를 하게 됩니다.
그다음에 정의해 주어야 할 것이 decisionVoters 입니다. 권한 체크를 할 떄 저 voter들을 순차적으로 호출 하면서, 권한이 있는지 실질적으로 체크 하게 됩니다. UnanimouseBased의 decide메서드를 살표보면 아래와 같은 로직을 실행합니다.
AffirmativeBased의 경우 한개라도 허가가 발생 하면 바로 return 하여 권한을 부여 하고, ConsensusBased는 찬성, 반대, 중립 표들을 비교 하여 찬성일 경우만, UnanimouseBased는 모두 찬성일 경우만 권한을 부여 하게 됩니다.
for (ConfigAttribute attribute : attributes) {
singleAttributeList.set(0, attribute);
for(AccessDecisionVoter voter : getDecisionVoters()) {
int result = voter.vote(authentication, object, singleAttributeList);
if (logger.isDebugEnabled()) {
logger.debug("Voter: " + voter + ", returned: " + result);
}
이 경우에는 "ROLE_BASE", "ACL_OBJECT_READ" 가 attributes 가 되겠고, getDecisionVoters()에서 가져온 voter들은 XML 설정 파일에서 정의한 roleVoter, aclObjectReadVoter, aclObjectWriterVoter가 됩니다.
각각의 방식으로 vote를 호출해서 로그인한 사용자가 권한이 있는지 없는지를 확인하게 됩니다.
스프링 시큐리티 ACL 권한의 종류.
BasePermission 클래스 확인하기
기본 권한으로는 READ, WRITE, CREATE, DELETE, ADMINISTRATION 권한을 가지고 있습니다.
만약 다른 권한을 만들고 싶다면, AbstractPermission를 확장하여 구현 하면 됩니다.
추가로 그럼 ACL DA 로직은 어디에 있는가 하는가 하면.
JdbcMutableAclService 클래스를 사용 하여 Acl 관련 서비스를 제공 합니다.
기본 쿼리가 PostregeSql 기본으로 되어 있기 때문에 각각 DB 벤더에 맞게 쿼리를 커스터마이징 해야합니다.
(call identity 등 ANSI 표준 쿼리가 아닌 것만 작성하면 됨)
프로그램 실행 화면.
소스 구성은 간단한 테스트 클래스와, ACL 을 활용한 게시판으로 구성 되어 있습니다.
소스에 첨부된 스키마대로 db를 설치 하고(mysql 기본) STS 최신버전(이클립스 스프링 버전, Spring tool suit 인가 ;)에서 첨부한 파일을 가져다가 실행 시키면 됩니다. 서버는 톰캣 6.0 으로 실행 시키시면 됩니다.
일단 서버를 실행 시키면
이런 화면이 표시 됩니다.
제가 전에 공부하던 소스를 가지고 구성한 것이라... 몇몇 소스가 동작하지 않을 수도 있습니다. ^^;
jquery plug-in을 몇개 포함하고 있습니다.
액션은 전부 jquery를 사용해서 ajax로 처리하도록 되어 있습니다.
글쓰기를 선택하면 글쓰기 화면이 표시되고, 제목을 선택하면 보기 화면으로 넘어갑니다.
jsp에서 권한을 체크하는 부분이 있는데, 이 부분을 보면 아래와 같습니다.
hasPermission 부분에서 접속한 사용자의 권한과 조회한 오브젝트의 ACL 권한을 비교해서 권한이 있을 경우에만 태그 안의 내용을 보여주게 됩니다.(삭제 및 수정 버튼 렌더링 처리)
아래 파일은 프로젝트 압축학 war 파일.
STS에서 불러서 쓰삼.
요즘 너무 노는데.
스타크래프트 좀 하고 하다보면 책도 안읽고 코딩도 안하고 그냥 널부러져서 잔다.
공포의 스타크래프트!!! 젝일 ! -_-
내일 휴가 낼 수 있으면 시큐리티 관련 부분 정리해서 샘플코드로 포스팅 할 수 있도록 하고
물론 봄싹에도...
지금 Acl 남은 부분이 권한을 획득한 다음에 또 다른 처리를 할 수 있는 부분인데..
여튼 이 부분만 처리 하면 대충 acl 관련해서는 다 된든 싶다.
url 보안, 메서드 보안, 도메인 보안 등 이렇게 적용하면 꽤 괜찮은 시스템이 될 듯 하다.
물론 권한 관련 설계를 좀 더 잘해야겠지만(조직도에 따른 권한의 경우)
하여.. 다음주까지 해서 대충 다 끝내고.
다음 달에 아이폰 4세대가 출시 되면
아마도 안드로이드폰 가격도 내릴 것으로 생각된다.(HTC 디자이어)
그러면 냅다 디자이어를 지르는거지!! 난 24개월 동안 SKT의 노예가 되는거야!! 올레!!!
다음주 중에도 쭉 휴가 기간 이면 봄싹 코드 분석을 다시 좀 해야겠다.
디비설계도 봐 보고 웹 네비게이션 설계쪽도 다시 봐 보고.
하이버네이트도 @_@
왜케 배울 것이 많은거임??
책은...
SI 프로젝트 전문가로 가는 길 하고 뷰티퓰 아키텍쳐 6월 까지 다 읽을 것.
7월달엔 안드로이드 책 보고 토비님 책 출간되면 그것도 봐야함.
SI 프로젝트 전문가로 가는 길.
accesscontrollist 태그를 쓸때 문제점.
</sec:accesscontrollist>
이렇게 하면 로그인한 사람의 권한이 acl Object의 권한과 일치 하는지 검색 하게 된다.
여기서 문제점이.. admin의 경우 permission 이 '16'이다.
admin은 하위 권한들을 가지고 있기 때문에 위 태그의 '8(delete, BasePermission)' 권한을 포함 해서 확인을 해야 하는데.
'16'이 모든 권한을 가지고 있으므로 '8' 일 경우에도 권한을 가지고 있어야 한다.
근데 aclObject는 admin이 이 객체에 대해서 16의 권한을 가지고 있어도
AclImpl 클래스의 isGranted에서 이를 == 비교로 하기 때문에 '16' 과 '8'은 다르기 때문에 권한이 있다고 표시 되지 않는다.
그럼 이를 변경 하기 위해서는 AclImp을 extends 해서 isGranted를 override 해야 하는가??
다른 방법으로 Permission을 비교하는 방법은 없을까?
음 좀 더 생각을 해 보자.
도메인 acl을 적용할 때
적용하는 SecurityService 클래스를 어디에 등록 해 주어야 하는가.
dao를 호출하는 서비스 클래스의 메서드에다가 aop를 걸어서(acl에 의존하지 않도록) 해 주면 되나??
각각 도메인 클래스마다 해당 securySevice클래스를 등록해 주어야 하는가?
작성자에 따라 글 에 대한 권한도 틀려질 텐데 이를 어떻게 해결할 것인가?
-> 롤 확인해서 롤에 따라 acls을 달리 부여 하면 될려나?
이거 원 산넘어 산이군 ㅋㅋ
스프링 시큐리티에서 acl 가져온후..
acl 값을 가져 온 후에 이 값들을 맵에 담게 된다.
근데 이 맵의 키가 ObjectIdentityImpl 인데, 요고에 담기는 키의 값들과, acl 값을 가져올 ObjectIdentityImpl 값이 같아야
acl 값들을 제대로 가져 올 수 있다.
근대, Object id 값을 비교 하는데 대상 Object의 id는 hashcode 값이 있는데, 맵에 담겨질 object의 id에는 hashcode 값이 없다.
하여 map.containsKey( target)으로 하여 비교 하면 hashcode로 비교를 하는데, 여기서 에러가 나서
voter가 AccessDenied로 투표를 한다.
꿱..
어려워 -_-
그래서 이거 넘어 갈려면.... hashcode 값도 담겨가게 하던가,
String 값 비교로 해야 할 것 같은데..
근데 전에 잘 된거 같은데. -_-;;
이 무슨 또 삽질을 -,.-;;
ObjectIdentityRetrievalStrategy를 구현한 클래스에서 getObjectIdentity 메서드가 ObjectIdentityImpl를 리턴 하는데..
여기서 스트링으로 identity를 주니 당연히 안되지 -_-;; long 값으로 주도록 변경.
이제 다음 단계에 접어 들어간다.
일주일 휴가 했더니 다 까먹었어.