복붙노트

[SPRING] AccessHeniedException - RoleHierarchyImpl를 사용하는 경우

SPRING

AccessHeniedException - RoleHierarchyImpl를 사용하는 경우

스프링 보안에서 역할 계층 구조를 사용하고 있습니다.

<beans:bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <beans:constructor-arg ref="roleHierarchy" />
</beans:bean>

<beans:bean id="roleHierarchy"
        class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <beans:property name="hierarchy">
        <beans:value>
            ROLE_USER > ROLE_GUEST
        </beans:value>
    </beans:property>
</beans:bean>

나는 protect-pointcut을 사용하는 방법을 확보하고있다.

<global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
  <protect-pointcut expression="execution(* my.package.*(..))"
     access="ROLE_GUEST"/>
</global-method-security>

그러나 권한이 ROLE_USER 인 사용자로 로그인하면 AccessDeniedException이 발생합니다. 내가 access = "ROLE_GUEST, ROLE_USER"인 protect-pointcut을 지정하면 아무런 문제가 없습니다.

몇 가지 단계가 빠졌습니까? 참고로 Spring 3.0.5를 사용하고 있습니다.

감사.

해결법

  1. ==============================

    1.버그 보고서 SEC-1163과 아래의 주석을보십시오.

    버그 보고서 SEC-1163과 아래의 주석을보십시오.

    그래서 당신은 다음과 같은 것이 필요합니다.

    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>              
                <ref bean="roleHierarchyVoter" />
                <ref bean="authenticatedVoter" />
                <ref bean="preAdviceVoter" />
                <ref bean="mediaItemReadVoter" />
                <ref bean="mediaItemWriteVoter" />
            </list>
        </property>
    </bean>
    
    <bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
        <constructor-arg ref="roleHierarchy"/>
    </bean>
    
  2. ==============================

    2.http 요소에서 표현식을 사용할 수 있도록 WebExpressionVoter를 추가하는 것을 잊지 마십시오.

    http 요소에서 표현식을 사용할 수 있도록 WebExpressionVoter를 추가하는 것을 잊지 마십시오.

    <sec:http use-expressions="true" access-decision-manager-ref="accessDecisionManager">
       <sec:intercept-url pattern="/index.html" access="hasRole('ROLE_AUTHENTICATED')" />
       <sec:intercept-url pattern="/admin" access="hasRole('ROLE_SUPERVISOR')" />
       ...
    

    그래서 나는 같은 roleHierarchyImpl 빈을 사용하는 역할 계층 유권자와 WebExpressionVoter를 포함하는 accessDecisionManager로 끝난다.

    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
      <property name="decisionVoters">
        <list>
           <ref bean="roleHierarchyVoter" />
           <bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
               <property name="expressionHandler">
                <bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
                   <property name="roleHierarchy" ref="roleHierarchy"/>
                </bean>
            </property>
           </bean>
           <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
        </list>
      </property>
    </bean>
    <bean id="roleHierarchyVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
        <constructor-arg ref="roleHierarchy" />
    </bean>
    
    <bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
        <property name="hierarchy">
            <value>
                ROLE_SUPERVISOR > ROLE_XX
                ROLE_XX > ROLE_AUTHENTICATED
                ROLE_AUTHENTICATED > ROLE_UNAUTHENTICATED
            </value>
        </property>
    </bean>
    

    (봄철 초 3.1)

  3. ==============================

    3.위의 jgraglia 예제에서는 중첩 된 bean이 약간 잘못되었으므로 WebExpressionVoter에서 계층 구조가 처리되므로 가 필요하지 않습니다. Spring Security 4.0.0에서이 작업을 수행하고 있지만 use-expressions = "true"가 필요하지 않다는 것을 제외하면 코드는 기본적으로 켜져 있기 때문에 동일하게 보입니다.

    위의 jgraglia 예제에서는 중첩 된 bean이 약간 잘못되었으므로 WebExpressionVoter에서 계층 구조가 처리되므로 가 필요하지 않습니다. Spring Security 4.0.0에서이 작업을 수행하고 있지만 use-expressions = "true"가 필요하지 않다는 것을 제외하면 코드는 기본적으로 켜져 있기 때문에 동일하게 보입니다.

    나는 보통 가능한 한 많이 콩을 중첩 시키려고한다. 그래서 내 코드는 필요하지 않으면 ref = ""값이 없다.

    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
       <constructor-arg>
            <bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
                <property name="expressionHandler" ref="webExpressionHandler" />
            </bean>
       </constructor-arg>
    </bean>
    
    <bean id="webExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
        <property name="roleHierarchy" ref="roleHierarchy"/>
    </bean>
    
    <bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
        <property name="hierarchy">
            <value>
                ROLE_ADMIN > ROLE_USER
                ROLE_USER > ROLE_ANONYMOUS
            </value>
        </property>
    </bean>
    
  4. from https://stackoverflow.com/questions/7809313/accessdeniedexception-if-using-rolehierarchyimpl by cc-by-sa and MIT license