如果使用 RoleHierarchyImpl,则 AccessDeniedException
Posted
技术标签:
【中文标题】如果使用 RoleHierarchyImpl,则 AccessDeniedException【英文标题】:AccessDeniedException if using RoleHierarchyImpl 【发布时间】:2011-12-10 04:38:24 【问题描述】:我在 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>
我正在使用保护切入点保护方法
<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。
谢谢。
【问题讨论】:
【参考方案1】:不要忘记添加一个 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')" />
...
所以我最终得到了一个 accessDecisionManager,其中包含一个角色层次投票者和一个 WebExpressionVoter,两者都使用相同的 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 节)
【讨论】:
【参考方案2】:上面的 jgraglia 示例中的嵌套 bean 略有错误,您不需要 <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>
【讨论】:
【参考方案3】:查看错误报告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>
【讨论】:
我看到,默认情况下,AffirmativeBased 实现用于 RoleVoter 和 AuthenticatedVoter。 static.springsource.org/spring-security/site/docs/3.0.x/…以上是关于如果使用 RoleHierarchyImpl,则 AccessDeniedException的主要内容,如果未能解决你的问题,请参考以下文章
Python使用pandas保存csv文件:如果文件存在则只添加内容(append),如果无表则同时写入表头和内容(write)
如果对象存在于全局中,则R从函数中从全局环境中获取对象,但如果不存在则使用不同的默认值
Postgres 如果不存在则插入多行,如果存在或插入则返回所有 id,然后使用所有 id 插入另一个表