====== Authorization ======
===== 개요 =====
웹 사이트에 존재하는 모든 사용자들은 사이트 정책에 따라 그 부류 별로 컨텐츠에 대한 접근이 제한 되는데 이것을 권한 부여(authorization)라 한다.\\
즉, 권한은 특정 사용자가 웹 사이트에서 제공하는 컨텐츠(정보 또는 기능)에 접근 가능한지를 판단하는 과정을 의미한다.
===== 설명 =====
Authorization은 XML 또는 DB에서 권한을 관리하며 계층적 권한을 지원한다.\\
\\
Server Security에서는 Filter Security Interceptor에 의해 처리되며, DB로부터 권한 정보를 처리하기 위해 다음과 같이 설정된다.
...
...
* authenticationManager : 설정의 의해 자동으로 생성되는 bean ID를 지정("org.springframework.security.authenticationManager")
* accessDecisionManager : 권한 부여 여부를 결정하는 Access Decision Manager로서 자동으로 생성되기 때문에 해당 bean ID를 지정하면 됨("org.springframework.security.access.vote.AffirmativeBased#0")
* securityMetadataSource : 권한 설정 정보에 대한 처리 담당
참고로 자동으로 등록되는 AccessDecisionManager는 다음과 같은 설정을 갖는다.
* org.springframework.security.vote.AffirmativeBased : 단 한 개의 오브젝트라도 허락하면 허가하는 방식으로 처리(기본 처리)
* org.springframework.security.vote.UnanimousBased : 모든 오브젝트가 허락해야 허가하는 방식으로 처리
* decisionVoters : 허가 오브젝트에 대한 목록을 설정함
==== 자원 관리 ====
=== url ===
요청되는 웹 url을 점검하여 DB에 저장된 url과 비교하여 접근권한을 지정할 수 있다.\\
ex: \\
\A/sale/.*\.do\Z
\\
\A/cvpl/((?!EgovCvplLogin\.do).)*\Z
== filterSecurityInterceptor ==
FilterSecurityInterceptor는 HTTP 자원의 보안을 처리할 책임이 있다.\\
다른 보안 인터셉터와 유사하게 FilterSecurityInterceptor는 AuthenticationManager와 AccessDecisionManager에 대한 참조를 필요로 한다.\\
또한 FilterSecurityInterceptor는 서로 다른 HTTP URL 요청에 적용되는 설정 속성도 설정한다.\\
== databaseSecurityMetadataSource ==
DB 기반으로 현재 시점의 url 보호자원-권한의 맵핑 정보를 Runtime 에 동적으로\\
변경 반영하기 위한 Spring Security 의 FilterInvocationSecurityMetadataSource 확장 클래스이다.
== requestMap ==
DB 기반의 보호자원 맵핑 정보를 얻어 이를 참조하는 빈의 초기화 데이터로 제공한다.\\
securedObjectService의 getRolesAndUrl()를 호출하여 DB에서 역할과 url의 매핑정보를 얻어온다.
=== method ===
Spring Security는 Spring의 DefaultAdvisorAutoProxyCreator와 함께 사용될 수 있는 MethodSecurityMetadataSourceAdvisor 처리를 제공하며, 이것을 이용하여 자동적으로 보안 인터셉터를 MethodSecurityInterceptor를 정의한 빈의 앞부분에 연결한다.\\
== methodSecurityMetadataSourceAdvisor ==
== methodSecurityInterceptor ==
메소드 요청에 대한 자원을 보호하기 위해 MethodSecurityInterceptor를 어플리케이션 Context에 추가해야하며 보안을 필요로 하는 빈이 인터셉터에 연결(chaining)된다.\\
이러한 연결은 Spring의 ProxyFactoryBean이나 BeanNameAutoProxyCreator를 이용하여 만들어지며, Spring의 여러 다른 부분들이 통상적으로 이용되는 방식과 유사하다.\\
MethodSecurityInterceptor 는 다음과 같이 설정한다.
== methodSecurityMetadataSources ==
== methodMap ==
DB 기반의 보호자원 맵핑 정보를 얻어 이를 참조하는 빈의 초기화 데이터로 제공한다.\\
resourceType을 method로 설정하여 securedObjectService의 getRolesAndMethod()를 호출하여 DB에서 역할과 메소드의 매핑정보를 얻어온다.
=== pointcut ===
DB 기반의 보호자원 맵핑 정보를 얻어 이를 참조하는 빈의 초기화 데이터로 제공한다.\\
resourceType을 pointcut으로 설정하여 securedObjectService의 getRolesAndPointcut()를 호출하여 DB에서 역할과 Pointcut의 매핑정보를 얻어온다.
ex: execution(* egovframework.rte.security..service.*Service.insert*(..))
==== 역할 관리 ====
역할은 상하 계층으로 관리하며 어플리케이션 Context 또는 DB에 저장하여 관리한다.
== XMl Context에 계층 역할을 등록하여 관리할 경우 ==
ROLE_ADMIN > ROLE_USER
ROLE_USER > ROLE_RESTRICTED
ROLE_RESTRICTED > IS_AUTHENTICATED_FULLY
IS_AUTHENTICATED_REMEMBERED > IS_AUTHENTICATED_ANONYMOUSLY
== DB에서 계층 역할을 관리할 경우 ==
* class : egovframework.rte.fdl.security.userdetails.jdbc.EgovJdbcUserDetailsManager
* usersByUsernameQuery : 사용자 인증을 위해 사용자 테이블에서 사용자정보를 조회한다.
* authoritiesByUsernameQuery : 사용자 인증을 위해 사용자권한 테이블에서 사용자권한정보를 조회한다.
* roleHierarchy : 역할의 계층적 관리를 위해 계층 역할을 설정한다.
* mapClass : 세션 사용을 위한 세션 쿼리 및 세션VO간의 매핑 클래스를 설정한다.
* dataSource : JDBC 서비스를 위한 dataSource를 설정한다.
== Configuration ==
아래의 속성쿼리는 SecuredObjectDAO 빈에 기본으로 내장되었으며 DBMS 벤더에 따른 SQL문 차이 또는 DB 스키마 차이로 인한 변경된 쿼리를 직접 반영할 수 있다.\\
내장된 기본 쿼리는 다음과 같다.
* sqlHierarchicalRoles
SELECT a.child_role child, a.parent_role parent
FROM ROLES_HIERARCHY a LEFT JOIN ROLES_HIERARCHY b on (a.child_role = b.parent_role)
* sqlRolesAndUrl
SELECT a.resource_pattern url, b.authority authority
FROM SECURED_RESOURCES a, SECURED_RESOURCES_ROLE b
WHERE a.resource_id = b.resource_id
AND a.resource_type = 'url' ORDER BY a.sort_order
* sqlRolesAndMethod
SELECT a.resource_pattern method, b.authority authority
FROM SECURED_RESOURCES a, SECURED_RESOURCES_ROLE b
WHERE a.resource_id = b.resource_id
AND a.resource_type = 'method' ORDER BY a.sort_order
* sqlRolesAndPointcut
SELECT a.resource_pattern pointcut, b.authority authority
FROM SECURED_RESOURCES a, SECURED_RESOURCES_ROLE b
WHERE a.resource_id = b.resource_id
AND a.resource_type = 'pointcut' ORDER BY a.sort_order
SecuredObjectDAO 빈에 내장된 SQL을 사용하지 않을 경우 아래와 같이 SQL을 지정하여 설정한다.
SELECT a.child_role child, a.parent_role parent
FROM ROLES_HIERARCHY a LEFT JOIN ROLES_HIERARCHY b on (a.child_role = b.parent_role)
SELECT a.resource_pattern url, b.authority authority
FROM SECURED_RESOURCES a, SECURED_RESOURCES_ROLE b
WHERE a.resource_id = b.resource_id
AND a.resource_type = 'url' ORDER BY a.sort_order
SELECT a.resource_pattern method, b.authority authority
FROM SECURED_RESOURCES a, SECURED_RESOURCES_ROLE b
WHERE a.resource_id = b.resource_id
AND a.resource_type = 'method' ORDER BY a.sort_order
SELECT a.resource_pattern pointcut, b.authority authority
FROM SECURED_RESOURCES a, SECURED_RESOURCES_ROLE b
WHERE a.resource_id = b.resource_id
AND a.resource_type = 'pointcut' ORDER BY a.sort_order
==== 세션사용 ====
=== 역할 가져오기 ===
List authorities = EgovUserDetailsHelper.getAuthorities();
// 1. authorites 에 권한이 있는지 체크 TRUE/FALSE
assertTrue(authorities.contains("ROLE_USER"));
assertTrue(authorities.contains("ROLE_RESTRICTED"));
assertTrue(authorities.contains("IS_AUTHENTICATED_ANONYMOUSLY"));
assertTrue(authorities.contains("IS_AUTHENTICATED_FULLY"));
assertTrue(authorities.contains("IS_AUTHENTICATED_REMEMBERED"));
// 2. authorites 에 ROLE 이 여러개 설정된 경우
for (Iterator it = authorities.iterator(); it.hasNext();) {
String auth = it.next();
}
// 3. authorites 에 ROLE 이 하나만 설정된 경우
String auth = (String) authorities.toArray()[0];
===== 참고자료 =====