3.Anyframe IAM Core Install

이번 장에서는 사용자 어플리케이션에 설치되어 인증 및 권한 제어를 담당하는 Anyframe IAM Core를 설치 하는 절차에 대해서 알아본다.

IAM Core 설치 절차는 다음과 같다.

3.1.library 카피

IAM Core 1.0.1 설치에는 jar 형식의 라이브러리 파일을 복사하는 과정이 필요하다.

아래의 jar 파일들은 Anyframe-iam-1.0.1-bin.zip 패키지에 포함된 anyframe.iam.sample-1.0.1.war 파일을 압축 해제하면 존재하는 WEB-INF/lib 디렉토리 이하에 위치한다. 입수된 jar 파일들을 해당 Web Application의 /WEB-INF/lib 폴더에 카피한다.

  • anyframe.iam.core-1.0.1.jar

  • anyframe.common-4.0.0.jar

  • spring-security-acl-2.0.4.jar

  • spring-security-core-2.0.4.jar

  • spring-security-core-tiger-2.0.4.jar

  • spring-security-taglibs-2.0.4.jar

3.2.Configuration

일반적인 경우 샘플 어플리케이션에서 제공하는 설정을 그대로 사용하면된다. 본 문서에서는 주요 설정 및 사용자 정의가 가능한 부분을 위주로 설명을 한다.

3.2.1.IAM Core Message 파일 설정

어플리케이션의 messageSource Bean 설정(주로 context-common.xml)에 IAM 메시지 파일을 추가한다.

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
        <list>
            ..
            <value>anyframe/iam/core/messages/security</value>
        </list>
    </property>
</bean>

3.2.2.Spring Security Filter Chain 설정

모든 웹 요청이 Spring Security의 DelegatingFilterProxy로 전달되도록 web.xml에 설정을 추가한다.

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3.2.3.IAM Admin Remote 연계 설정

보호대상 자원 정보 수집 및 런타임 갱신을 IAM Admin에서 Remote로 처리 할 수 있는 설정을 spring-security-servlet.xml 파일에 추가한다.

특별한 경우가 아니라면 샘플에서 제공하는 설정을 그대로 사용해도 무방하다. 다만 Resource 정보 수집시 추가적으로 제외하고 싶은 자원이 있는 경우 아래와 같이 설정을 한다.

아래의 설정은 패키지 명이 org, net, java, anyframe(단 anyframe.iam.sample로 시작하는 자원은 제외)으로 시작하는 자원을 정보 수집 대상에서 제외하는 설정의 예이다.

<bean id="resourceGatherAssistService"
    class="anyframe.iam.core.assist.impl.ResourceGatherAssistServiceImpl" >
    <property name="filterPatterns">
        <list>
            <value>(?!anyframe\.iam\.sample\..*)anyframe\..*</value>
            <value>org\..*</value>
            <value>net\..*</value>
            <value>java\..*</value>
        </list>
    </property>
</bean>

3.2.4.인증 및 권한 설정

이하 세팅은 context-spring-security.xml 파일에 적용한다.

http 하위 태그로 form-login을 지정하여 Form 기반 인증을 설정하고 login-page, login-processing-url, authentication-failure-url, default-target-url을 지정한다.

login-processing-url는 반드시 /j_spring_security_check 로 설정한다.

또한 logout 태그를 이용하여 logout 성공후에 이동할 페이지를 지정한다.

<http path-type="regex" lowercase-comparisons="false">
    <form-login login-page="/common/login.do" login-processing-url="/j_spring_security_check"
        authentication-failure-url="/common/login.do?login_error=1"
        default-target-url="/index.jsp?flag=L" />

        <anonymous />
        <logout logout-success-url="/index.jsp" />
</http>

jdbcUserService Bean의 property 설정으로 사용자 인증과 권한(Role) 정보에 대한 쿼리를 설정한다.

usersByUsernameQuery의 경우 USER_ID, PASSWORD, ENABLED 필드는 항상 1,2,3 번째 순서로 나타나야만 한다.

<b:bean id="jdbcUserService"
    class="anyframe.iam.core.userdetails.jdbc.ExtJdbcUserDetailsManager" >
    <!-- USER_ID, PASSWORD, ENABLED 는 항상 1,2,3 번째 순서로 나타나야 함!! -->
    <b:property name="usersByUsernameQuery" value="SELECT USER_ID, PASSWORD, CASE WHEN ENABLED = 'Y' THEN 1 ELSE 0 END ENABLED, USER_NAME, CREATE_DATE, MODIFY_DATE FROM USERS WHERE USER_ID = ?"/>
    <b:property name="authoritiesByUsernameQuery">
        <b:value>
            SELECT USER_ID,ROLE_ID,GROUP_ID,SUBJECT_ID,TYPE
            FROM AUTHORITIES C, (
                SELECT A.USER_ID,B.GROUP_ID
                FROM USERS A LEFT OUTER JOIN GROUPS_USERS B ON ( A.USER_ID = B.USER_ID )
                WHERE A.USER_ID = ? ) D
            WHERE ( C.SUBJECT_ID = D.USER_ID
                OR C.SUBJECT_ID = D.GROUP_ID )
        </b:value>
    </b:property>
    <b:property name="dataSource" ref="dataSource"/>
</b:bean>

3.2.5.SecuredObject 설정

이하 세팅은 context-spring-security.xml 파일에 적용한다.

IAM 에서는 Spring Security 의 보호자원, RoleHierarchy 정보, 확장한 Time 기반의 보호자원에 대한 데이터를 DB 기반으로 처리하고 있다.

SecuredObject에 대한 기본설정은 아래와 같다. IAM에서 제공하는 DB를 사용 할 경우 아래의 설정만으로 충분하다.

<b:bean id="securedObjectService" class="anyframe.iam.core.securedobject.impl.SecuredObjectServiceImpl">
    <b:property name="securedObjectDAO" ref="securedObjectDAO" />
</b:bean>

<b:bean id="securedObjectDAO" class="anyframe.iam.core.securedobject.impl.SecuredObjectDAO">
    <b:property name="dataSource" ref="dataSource" />
</b:bean>

3.2.6.SecuredObject 사용자화 설정

이하 세팅은 context-spring-security.xml 파일에 적용한다.

만약 IAM에서 제공하는 DB Schema를 동일하게 사용 할 수 없어 별도의 사용자화가 필요한 경우, SecuredObject에 대한 사용자 설정을 통해서 IAM Core의 적용이 가능하다.

사용자 설정은 아래와 같이 securedObjectDAO bean의 하위에 property 설정을 통해 가능하다. 단, 이 경우 IAM Admin Console 사용을 위해서는 customizing이 필요하다.

<b:bean id="securedObjectDAO" class="anyframe.iam.core.securedobject.impl.SecuredObjectDAO">
    <b:property name="dataSource" ref="dataSource" />
    <b:property name="sqlRolesAndUrl">
        <b:value>
            SELECT a.resource_pattern url, b.role_id authority
            FROM secured_resources a, secured_resources_roles b
            WHERE a.resource_id = b.resource_id
                AND a.resource_type = 'url'
            ORDER BY a.sort_order, a.resource_id
        </b:value>    	
    </b:property>
</b:bean>

사용자 설정이 가능한 Secured Object 항목과 기본 쿼리는 다음과 같다.

  • sqlRolesAndUrl : url 형식 보호자원-Role 매핑

    SELECT a.resource_pattern url, b.role_id authority
    FROM secured_resources a, secured_resources_roles b
    WHERE a.resource_id = b.resource_id
        AND a.resource_type = 'url'
    ORDER BY a.sort_order, a.resource_id

  • sqlRolesAndMethod : method 형식 보호자원-Role 매핑

    SELECT a.resource_pattern url, b.role_id authority
    FROM secured_resources a, secured_resources_roles b
    WHERE a.resource_id = b.resource_id
        AND a.resource_type = 'method'
    ORDER BY a.sort_order, a.resource_id

  • sqlRolesAndPointcut : pointcut 형식 보호자원-Role 매핑

    SELECT a.resource_pattern url, b.role_id authority
    FROM secured_resources a, secured_resources_roles b
    WHERE a.resource_id = b.resource_id
        AND a.resource_type = 'pointcut'
    ORDER BY a.sort_order, a.resource_id

  • sqlRegexMatchedRequestMapping : request best matching url 보호자원-Role 매핑

    SELECT a.resource_pattern uri, b.role_id authority
    FROM secured_resources a, secured_resources_roles b
    WHERE a.resource_id = b.resource_id
        AND a.resource_id =
            ( SELECT resource_id FROM
                ( SELECT resource_id, ROW_NUMBER() OVER (ORDER BY sort_order) resource_order FROM secured_resources c
                WHERE REGEXP_LIKE ( :url, c.resource_pattern )
                    AND c.resource_type = 'url'
                ORDER BY c.sort_order )
            WHERE resource_order = 1 )

  • sqlHierarchicalRoles : Role 계층구조

    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)

  • sqlRestrictedTimesRoles : 실행시간 권한제어 restricted times roles 매핑

    SELECT time_type, a.time_id as time_id, start_date, start_time, end_date, end_time, role_id
    FROM restricted_times a, restricted_times_roles b
    WHERE a.time_id = b.time_id
    ORDER BY time_type, start_date, start_time, end_date, end_time

  • sqlRestrictedTimesResources : 실행시간 권한제어 restricted times resources 매핑

    SELECT time_type, a.time_id as time_id, start_date, start_time, end_date, end_time, b.resource_id as resource_id, resource_pattern, role_id as exclusion_role_id
    FROM restricted_times a,
        restricted_times_resources b left outer join times_resources_exclusion c
        on (b.time_id = c.time_id and b.resource_id = c.resource_id)
        , secured_resources d
    WHERE a.time_id = b.time_id
        AND b.resource_id = d.resource_id
        AND d.resource_type = 'url'
    ORDER BY d.sort_order, time_type, start_date, start_time, end_date, end_time

  • sqlViewResourceMapping : 조건(ROLE 리스트, 사용자 아이디)에 따른 view resource 매핑(sqlViewResourceMapping)

    SELECT view_resource_id, ref_type, ref_id, mask, permissions
    FROM view_resources_mapping
    WHERE view_resource_id = :viewResourceId
        AND (
            ( ref_id IN ( {{userRoleList}} ) AND ref_type = 'ROLE' )
            OR ( ref_id = :userId AND ref_type = 'USER' )
            OR ( ref_id = :groupId AND ref_type = 'GROUP' )
        )
    ORDER BY CASE ref_type WHEN 'USER' THEN 1 WHEN 'GROUP' THEN 2 WHEN 'ROLE' THEN 3 ELSE 10 END, ref_id

3.2.7.보호 예외 대상 자원 설정

이하 세팅은 context-spring-security.xml 파일에 적용한다.

모든 요청에 대해서 Spring Security Filter Chain을 통해 처리 하지만 보호 예외 대상으로 등록 할 경우 Filter Chain을 거지치 않고 자원을 제공한다.(일반적으로 image, css, js 파일등에 대해서 설정한다.)

http 하위의 intercept-url 태그로 보호 예외 대상 자원에 대해 filters="none" 을 지정한다.

<http path-type="regex" lowercase-comparisons="false">
    <intercept-url pattern="\A/sample/images/.*\Z" filters="none" />
    <intercept-url pattern="\A/sample/css/.*\Z" filters="none" />
    <intercept-url pattern="\A/sample/javascript/.*\Z" filters="none" />
</http>

3.2.8.Role 설정

이하 세팅은 context-spring-security.xml 파일에 적용한다.

계층형 구조의 Role 정보를 사용할 경우 아래와 같이 설정한다. IAM은 기본적으로 계층형 Role 정보를 사용하도록 설정되어 있다. (Role 정보를 가져오는 방법은 Secured Object 설정을 참조한다.) 만약 계층형 Role 구조를 사용하지 않으려면 설정하지 않는다.

<b:bean id="roleHierarchy" class="org.springframework.security.userdetails.hierarchicalroles.RoleHierarchyImpl">
    <b:property name="hierarchy" ref="hierarchyStrings" />
</b:bean>

<b:bean id="hierarchyStrings" class="anyframe.iam.core.userdetails.hierarchicalroles.HierarchyStringsFactoryBean" init-method="init">
    <b:property name="securedObjectService" ref="securedObjectService" />
</b:bean>

3.2.9.View Resource 에 대한 ACL 설정

이하 세팅은 context-spring-security.xml 파일에 적용한다.

사용자가 정의한 View Resource에 대해 매핑된 Permission 을 체크할 수 있는 기능을 제공한다. 대상 시스템에 필요한 권한을 선택적으로 적용 할 수 있다.

  • 기본 권한 : READ, WRITE, CREATE, DELETE, ADMINISTRATION

  • 추가 권한 : LIST, PRINT, REPORT, POPUP, DOWNLOAD, UPLOAD, HELP

  • 기타 예약 권한 : FNC0, FNC1, FNC2, FNC3, FNC4, FNC5, FNC6, FNC7, FNC8, FNC9

다음은 READ, WRITE, CREATE, DELETE, DOWNLOAD 권한만을 설정한 예제이다.

<b:bean id="viewResourceAccessService"
    class="anyframe.iam.core.acl.impl.ViewResourceAccessServiceImpl">
    <b:property name="securedObjectService" ref="securedObjectService" />
    <b:property name="registeredPermissions">
        <b:list>
            <b:ref local="anyframe.iam.core.acl.ExtBasePermission.READ" />
            <b:ref local="anyframe.iam.core.acl.ExtBasePermission.WRITE" />
            <b:ref local="anyframe.iam.core.acl.ExtBasePermission.CREATE" />
            <b:ref local="anyframe.iam.core.acl.ExtBasePermission.DELETE" />
            <b:ref local="anyframe.iam.core.acl.ExtBasePermission.DOWNLOAD" />
        </b:list>
    </b:property>
</b:bean>

<b:bean id="anyframe.iam.core.acl.ExtBasePermission.READ"
    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
    <b:property name="staticField"
        value="anyframe.iam.core.acl.ExtBasePermission.READ" />
</b:bean>
<b:bean id="anyframe.iam.core.acl.ExtBasePermission.WRITE"
    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
    <b:property name="staticField"
        value="anyframe.iam.core.acl.ExtBasePermission.WRITE" />
</b:bean>
<b:bean id="anyframe.iam.core.acl.ExtBasePermission.CREATE"
    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
    <b:property name="staticField"
        value="anyframe.iam.core.acl.ExtBasePermission.CREATE" />
</b:bean>
<b:bean id="anyframe.iam.core.acl.ExtBasePermission.DELETE"
    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
    <b:property name="staticField"
        value="anyframe.iam.core.acl.ExtBasePermission.DELETE" />
</b:bean>
<b:bean id="anyframe.iam.core.acl.ExtBasePermission.DOWNLOAD"
    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
    <b:property name="staticField"
        value="anyframe.iam.core.acl.ExtBasePermission.DOWNLOAD" />
</b:bean>