Reputation: 3753
I have a custom authentication provider that's returning a concrete implementation of 'AbstractAuthenticationTokenwith
ROLE_ADMINonly. I have a method annotated with
@PreAuthorize("hasRole('ROLE_USER')")`. I'm trying to set up a role hierarchy to give my admin user access to this method.
I have the following in my spring-security.xml:
<beans:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<beans:property name="hierarchy">
<beans:value>
ROLE_ADMIN > ROLE_USER
</beans:value>
</beans:property>
</beans:bean>
<beans:bean id="methodExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<beans:property name="roleHierarchy" ref="roleHierarchy" />
</beans:bean>
<sec:global-method-security pre-post-annotations="enabled">
<sec:expression-handler ref="methodExpressionHandler" />
</sec:global-method-security>
The request to the protected method gets denied, although it works if I change the annotation to @PreAuthorize("hasRole('ROLE_ADMIN')")
.
I put a breakpoint on the AccessDeniedException
, which was being thrown from AffirmativeBased.decide(...)
. The issue appears to be that the PreInvocationAuthorizationAdviceVoter
's expressionHandler
is null
. That suggests to me that there's something wrong in my wiring up of my roleHierarchy or methodExpressionHandler.
I there anything obviously wrong with my spring-security.xml? Is there something I'm misunderstanding about how this stuff should be working?
Upvotes: 1
Views: 1642
Reputation: 3753
Oh how silly of me... There's not enough context in my question to answer this, but I've resolved it.
I had <global-method-security>
in both my spring-security.xml
and my dispatcher-servlet.xml
. I was only making changes within spring-security.
The give-away was when I put a break point on DefaultMethodSecurityExpressionHandler
's constructor. It was being called twice. One was having setRoleHierarchy
called, the other wasn't.
The solution was:
spring-security.xml
and dispatcher-servlet.xml
.<global-method-security>
and the methodExpressionHandler
bean from spring-security.xml
to dispatcher-servlet.xml
.Upvotes: 1
Reputation: 7817
Try to inject roleHierarhy
into roleVoter
. Example from the official documentation:
<bean id="roleVoter" 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_ADMIN > ROLE_STAFF
ROLE_STAFF > ROLE_USER
ROLE_USER > ROLE_GUEST
</value>
</property>
</bean>
Upvotes: 0