如果使用RoleHierarchyImpl,则为AccessDeniedException

时间:2011-10-18 14:55:33

标签: spring spring-security

我在Spring Security中使用角色层次结构。

<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"指定保护切入点,我没有问题。

我错过了一些步骤吗?仅供参考,我使用的是Spring 3.0.5。

感谢。

3 个答案:

答案 0 :(得分:8)

不要忘记添加WebExpressionVoter以便能够在http元素中使用表达式:

<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')" />
   ...

所以我最终得到一个包含角色层次结构投票者和WebExpressionVoter的accessDecisionManager,两者都使用相同的roleHierarchyImpl bean。

<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节)

答案 1 :(得分:3)

嵌套bean在上面的jgraglia示例中略有错误,并且您不需要<ref bean="roleHierarchyVoter" />,因为层次结构是在WebExpressionVoter中处理的。我在Spring Security 4.0.0中执行此操作,但代码看起来相同,除非您不需要use-expressions="true",因为默认情况下它已启用。

我通常会尝试尽可能地嵌套我的bean,因此除非需要,否则我的代码没有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>

答案 2 :(得分:2)

查看错误报告SEC-1163以及下面的评论。

  

如果您需要对角色层次结构的基本支持,请使用RoleHierarchyVoter而不是RoleVoter。

所以你需要一些想法:

<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>