Spring Security

개발자세상 2009. 12. 21. 19:22

B3 진행하면서 Spring 의 Remoting 호출을 지원하면서 해당 호출을 Login Base로 진행하기 위해서 Spring Security를 두가지 방식으로 지원하게 되었다.

하나는 Config 설정에 의한 , 다른 하나는 LDAP Base.

어차피 Spring Security의 로그인이 Filter Chain을 적용하는 것이기에 Multiple Filter Chain을 확인해 봤더니 Login Path를 통해서 Multiple Filter Chain을 지원하고 있었다.

우선 web.xml 을 변경하여야 한다.

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>springSecurityFilterChain</param-value>
        </init-param>
    </filter>

보통의 경우는 springSecurityFilterChain 만 선언하면 문제가 없는데
multiple 한 fileter chain을 명시적으로 Spring Security Config에 선언해 주어야 하기 때문에 반드시 targetBeanName을 선언하여 value에는 Spring Security 설정에서 사용한 FilterChain Bean Name을 선언해 주어야 한다.

Spring Security 내부의 Filter Chain이 아닌 명시적인 Filter Chain을 사용하여야 하기 때문에 사용하는 방식에 맞추어 Filter Chain Config를 선언하여야 한다.

    <bean id="springSecurityFilterChain" class="org.springframework.security.util.FilterChainProxy">
        <s:filter-chain-map path-type="ant">
            <s:filter-chain pattern="/batchProcessService/**" filters="httpSessionContextIntegrationFilter,digestProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor" />
            <s:filter-chain pattern="/approvalProcessService/**" filters="httpSessionContextIntegrationFilter,digestProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor" />
            <s:filter-chain pattern="/**" filters="ldapHttpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,ldapExceptionTranslationFilter,sessionFixationProtectionFilter,ldapFilterInvocationInterceptor"/>
        </s:filter-chain-map>
    </bean>

web.xml 에서 선언했던 filterChain을 위와 같이 설정한다.
filter-chain의 pattern attribute에 선언된 URL에 맞추어 각각 선언된 Filter Chain이 적용이 된다.

위의 경우
/approvalProcessService/** 및 /batchProcessService/** URL은는"httpSessionContextIntegrationFilter,digestProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor" Filter Chain이
그 이외의 URL들은
"ldapHttpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,ldapExceptionTranslationFilter,sessionFixationProtectionFilter,ldapFilterInvocationInterceptor"
Filter Chain이 적용되게 된다.

LDAP 을 위해서는 아래의 Bean을 명시적으로 선언하였다.
물론 다른 것에 대해서도 해야 겠지만.^^

    <bean id="ldapHttpSessionContextIntegrationFilter" class="org.springframework.security.context.HttpSessionContextIntegrationFilter" />

    <bean id="logoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
        <constructor-arg value="로그아웃 후 Redirect될 페이지 URL" />
            <constructor-arg>
                <list>
                    <bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler" />
                </list>
            </constructor-arg>
        <property name="filterProcessesUrl" value="/j_spring_security_logout" />
         ( Logout Process Path URL )
    </bean>

    <bean id="authenticationProcessingFilter"    class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
        <property name="authenticationManager"         ref="ldapAuthenticationManager" />
        <property name="authenticationFailureUrl"     value="/ldapLogin.zul?error=1" />
        <property name="defaultTargetUrl"            value="로그인 시 기본 Redirect 페이지 URL" />
        <property name="filterProcessesUrl"            value="/j_spring_security_check" />
    </bean>

    <bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter" />

    <bean id="anonymousProcessingFilter" class="org.springframework.security.providers.anonymous.AnonymousProcessingFilter">
        <property name="key" value="doesNotMatter" />
        <property name="userAttribute" value="roleAnonymous, ROLE_ANONYMOUS" />
    </bean>           

    <bean id="ldapExceptionTranslationFilter" class="org.springframework.security.ui.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
            <bean class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                <property name="loginFormUrl" value="로그인 입력화면 URL" />

            </bean>
        </property>
        <property name="accessDeniedHandler">
            <bean class="org.springframework.security.ui.AccessDeniedHandlerImpl">
            </bean>
        </property>
    </bean>

    <bean id="sessionFixationProtectionFilter" class="org.springframework.security.ui.SessionFixationProtectionFilter" />

    <bean id="ldapFilterInvocationInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
        <property name="authenticationManager" ref="ldapAuthenticationManager" />
        <property name="accessDecisionManager" ref="ldapAccessDecisionManager" />
        <property name="objectDefinitionSource">
            <s:filter-invocation-definition-source>
                <s:intercept-url pattern="/siteList/**" access="IS_AUTHENTICATED_REMEMBERED"/>
                <s:intercept-url pattern="/**"             access="IS_AUTHENTICATED_ANONYMOUSLY"/>
            </s:filter-invocation-definition-source>                       
        </property>
    </bean>

    <bean id="secondLdapProvider"
        class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
        <s:custom-authentication-provider />
        <constructor-arg>
            <bean               class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
                <constructor-arg ref="contextSource" />
                <property name="userSearch">
                    <bean id="userSearch"                        class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
                        <constructor-arg index="0" value="" />
                        <constructor-arg index="1" value="(&amp;(sAMAccountName={0})(objectclass=user))" />                       
                    </bean>
                </property>
            </bean>
        </constructor-arg>
        <constructor-arg>
            <bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
                <constructor-arg ref="contextSource" />
                <constructor-arg value="" />
                <property name="groupSearchFilter" value="(&amp;(member={0})(|(cn=B3 Reader)(cn=B3 Approval)))" />               
                <property name="rolePrefix" value="ROLE_" />
                <property name="searchSubtree" value="true" />
                <property name="convertToUpperCase" value="false" />
            </bean>
        </constructor-arg>
    </bean>

'개발자세상' 카테고리의 다른 글

Long Term Plan?  (0) 2011.02.19
이젠 모바일인가...  (2) 2010.12.05
ASP.NET 크레튜 강의 수강 소감  (0) 2009.12.15
티맥스 소식  (0) 2009.11.10
강사의 조건  (1) 2009.10.22
Posted by headiron
,