TAM Webseal + spring pre-authentication - spring

Has anybody done spring pre-authentication with TAM Web-seal?
Can you please share the configuration details?

If webseal forward the request with the username in iv-user header, then it is relative simple to configure spring-security:
<security:http auto-config="false" use-expressions="true" entry-point-ref="authenticationEntryPoint" access-decision-manager-ref="httpAccessDecisionManager">
<security:custom-filter ref="webSealPreAuthFilter" position="PRE_AUTH_FILTER"/>
...
</security:http>
<bean id="webSealPreAuthFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="principalRequestHeader" value="iv-user"/>
<!-- exceptionIfHeaderMissing AND checkForPrincipalChanges needs to be enable to check that each request needs a "iv-user" header -->
<property name="checkForPrincipalChanges" value="true"/>
<property name="exceptionIfHeaderMissing" value="true"/>
</bean>
<alias name="authenticationManager" alias="org.springframework.security.authenticationManager"/>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="authenticationEventPublisher">
<bean class="org.springframework.security.authentication.DefaultAuthenticationEventPublisher"/>
</property>
<constructor-arg name="providers">
<list>
<ref local="preAuthenticatedAuthenticationProvider"/>
</list>
</constructor-arg>
</bean>
<bean id="preAuthenticatedAuthenticationProvider"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<constructor-arg name="userDetailsService" ref="userDetailsService"/>
</bean>
</property>
</bean>
<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
You need an userDetailsService but this is highly dependend on how your application works.

Related

Release the attribute from CAS to Spring security

I am using a Spring security 3.X on the client side and CAS 4.0 on the server.
When i am doing CAS+Spring security integration, I am able to reach the level of ticket validation success and able to get the proper roles at the client side.
But I have added the following lines in my casServiceValidationSuccess.jsp to iterate and send the attributes in my response as my attributes are not released properly:
<cas:attributes>
<cas:user>${fn:escapeXml(assertion.primaryAuthentication.principal.id)}</cas:user>
<c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
</c:forEach>
</cas:attributes>
So wants to know is there any other alternative changes to do in deployerConfigContext.xml in the CAS server side to release particular attribute-"authorities" in my case and to get the same in SPRING client side.
Find the snippets of existing deployerConfigContext.xml where trying to release "authorities" attributes:
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
<constructor-arg>
<map>
<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
</map>
</constructor-arg>
<bean id="primaryAuthenticationHandler" class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="SELECT EMAIL FROM USER_DATA WHERE UserID = ?" />
</bean>
<bean id="primaryPrincipalResolver"
class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
<property name="attributeRepository" ref="attributeRepository" />
</bean>
<bean id="attributeRepository"
class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">
<constructor-arg index="0" ref="dataSource" />
<constructor-arg index="1" value="SELECT UserID, UserROLES FROM USER_DATA WHERE {0}" />
<property name="queryAttributeMapping">
<map>
<entry key="username" value="UserID" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="UserID" value="username" />
<entry key="UserROLES" value="UserROLES" />
</map>
</property>
</bean>
<bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">
<property name="registeredServices">
<list>
<bean class="org.jasig.cas.services.RegisteredServiceImpl">
<property name="id" value="0"></property>
<property name="name" value="HTTP"></property>
<property name="description" value="Only Allows HTTP Urls"></property>
<property name="serviceId" value="http://**" />
<property name="usernameAttribute" value="username" />
<property name="ignoreAttributes" value="false" />
<property name="allowedAttributes">
<list>
<value>UserROLES</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
Also find the security-context.xml at the spring client side:
<security:http use-expressions="true" entry-point-ref="casAuthenticationEntryPoint"
auto-config="true">
<security:custom-filter position="CAS_FILTER"
ref="casAuthenticationFilter"></security:custom-filter>
<security:intercept-url pattern="/home" access="hasRole('ROLE_TEST')"></security:intercept-url>
<security:intercept-url pattern="/**" access="hasRole('ROLE_ANONYMOUS')"></security:intercept-url>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="casAuthenticationProvider"></security:authentication-provider>
</security:authentication-manager>
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="http://localhost:7080/test/j_spring_cas_security_check"></property>
<property name="sendRenew" value="false"></property>
</bean>
<bean id="casAuthenticationFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="authenticationFailureHandler">
<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="http://localhost:8090/cas-server-webapp-4.0.0/login"/>
</bean>
</property>
<property name="authenticationSuccessHandler">
<bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/home.jsp"/>
</bean>
</property>
</bean>
<bean id="casAuthenticationEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl"
value="http://localhost:8090/cas-server-webapp-4.0.0/login"></property>
<property name="serviceProperties" ref="serviceProperties"></property>
</bean>
<!-- Handles the CAS ticket processing. -->
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<!-- <property name="userDetailsService" ref="userService"></property> -->
<property name="authenticationUserDetailsService" ref="authenticationUserDetailsService" />
<property name="serviceProperties" ref="serviceProperties"></property>
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0"
value="http://localhost:8090/cas-server-webapp-4.0.0">
</constructor-arg>
</bean>
</property>
<property name="key" value="cas"></property>
</bean>
<bean id="authenticationUserDetailsService"
class="org.springframework.security.cas.userdetails.GrantedAuthorityFromAssertionAttributesUserDetailsService">
<constructor-arg>
<list>
<value>UserROLES</value>
</list>
</constructor-arg>
</bean>
</beans>
Disclaimer: I'm the Chairman of CAS and founder of CAS in the cloud (https://www.casinthecloud.com).
Is your attribute person DAO referenced by your authentication handler? Does it work without Spring security doing a manual service ticket validation?

No AuthenticationProvider found for SAMLAuthenticationToken

I am using SSOCircle as IDP provider and using spring SAML. I have logged into SSOCircle and created a new SP and configured the unique entityID in securityContext.xml
I am able to see idp selection page but not able to see the login page. the configuration which is added are as follows
<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg>
<list>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
<constructor-arg>
<bean class="java.util.Timer"/>
</constructor-arg>
<constructor-arg>
<bean class="org.opensaml.util.resource.ClasspathResource">
<constructor-arg value="/conf/spring_saml_metadata.xml"/>
</bean>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="local" value="true"/>
<property name="securityProfile" value="metaiop"/>
<property name="sslSecurityProfile" value="pkix"/>
<property name="sslHostnameVerification" value="default"/>
<property name="signMetadata" value="false"/>
<property name="signingKey" value="apollo"/>
<property name="encryptionKey" value="apollo"/>
<property name="requireArtifactResolveSigned" value="false"/>
<property name="requireLogoutRequestSigned" value="false"/>
<property name="requireLogoutResponseSigned" value="false"/>
<property name="idpDiscoveryEnabled" value="true"/>
<property name="idpDiscoveryURL" value="http://localhost:8080/myApp/saml/discovery"/>
<property name="idpDiscoveryResponseURL" value="http://localhost:8080/myApp/saml/login?disco=true"/>
</bean>
</constructor-arg>
</bean>
<bean class="org.opensaml.saml2.metadata.provider.HTTPMetadataProvider">
<constructor-arg>
<value type="java.lang.String">http://idp.ssocircle.com/idp-meta.xml</value>
</constructor-arg>
<constructor-arg>
<value type="int">15000</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</list></constructor-arg>
</bean>
Entity ID is configured as mentioned below
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<!-- <property name="entityId" value="urn:test:user:city"/> -->
<property name="entityId" value="urn:myApp:useruser:dub"/>
<property name="requestSigned" value="true"/>
</bean>
</constructor-arg>
</bean>
The exception is below
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.saml.SAMLAuthenticationToken
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:196)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:84)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
The exception indicates that your AuthenticationProvider is missing instance of the org.springframework.security.saml.SAMLAuthenticationProvider, make sure that your securityContext.xml contains definition of the SAML auhentication provider, similar to the following:
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="samlAuthenticationProvider"/>
</security:authentication-manager>
I had the same exact issue and I added my samlAutheticationProvider in spring xml as stated by #Vladimir. I still got the same exception. When I debugged the code and logged the authentication managers available, I couldn't find my new saml authentication manager.
When I added the "id" in the security:authentication-manager, it worked fine.
<security:authentication-manager alias="samlAuthenticationManager" id="samlAuthenticationManager">
<!-- Register authentication manager for SAML provider -->
<security:authentication-provider ref="samlAuthenticationProvider"/>
</security:authentication-manager>
Hope this helps.

weblogic security realm with spring security filters

I am using spring security 3.1.1 for authentication.Application is deployed in weblogic server with security realm enabled for accessing datasource. for servlets I can give
<run-as>
<role-name>testrole</role-name>
</run-as>
how do i do the same for spring security filters. I am getting this error while accessing datasource from filters
: User "" does not have permission to perform operation "reserve" on resource "jdbc/DataSource"
securityContext.xml
<context:annotation-config/>
<sec:http use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint" >
<sec:intercept-url pattern="/**" access="permitAll"/>
<sec:custom-filter position="LOGOUT_FILTER" ref="LogoutFilter" />
<sec:custom-filter position="BASIC_AUTH_FILTER" ref="AuthenticationFilter"/>
</sec:http>
<bean id="LogoutFilter" class="com.xxx.LogoutFilter">
<constructor-arg>
<bean class="com.xxx.LogoutSuccessHandler"></bean>
</constructor-arg>
<constructor-arg>
<list>
<bean class="com.xxx.LogoutHandler"></bean>
</list>
</constructor-arg>
</bean>
<bean id="AuthenticationFilter" class="com.xxx.AuthenticationFilter" >
<constructor-arg type="java.lang.String">
<value>/login.do</value>
</constructor-arg>
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="successHandler" />
<property name="authenticationFailureHandler" ref="failureHandler" />
</bean>
<bean id="loginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/common/dologin.jsp" />
</bean>
<bean id="successHandler" class="com.xxx.AuthSuccessHandler"/>
<bean id="failureHandler" class="com.xxx.AuthFailureHandler"/>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="jaasAuthenticationProvider" />
</sec:authentication-manager>
<bean id="jaasAuthenticationProvider"
class="com.xxx.JaasAuthenticationProvider">
<property name="callbackHandlers">
<list>
<bean class="com.xxx.security.callback.SecurityInfoProvider">
</bean>
</list>
</property>
<property name="authorityGranters">
<list>
<bean class="com.xxx.security.action.RoleUserAuthorityGranter" />
</list>
</property>
</bean>
</beans>
May you could consider a solution as the following.
<bean id="securedJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.provider.url">t3://myServerA:8001,myServerB:8002</prop>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.security.principal">weblogic</prop>
<prop key="java.naming.security.credentials">weblogic</prop>
</props>
</property>
</bean>
<bean id="targetDatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref local="securedJndiTemplate"/>
</property>
<property name="jndiName">
<value>myWeblogicJNDI</value>
</property>
</bean>
In your java code try to lookup the targetDatasource.
I hope this solves your issue.

Session gets timed out sooner than expected when using Spring Security

I'm using Spring Security 3.1 and I'm facing a problem with session time outs.
I've set session time-out in the web.xml as follows:
<session-config>
<session-timeout>
45
</session-timeout>
</session-config>
So session is supposed to be expired after 45 minutes.
However I've noticed that session is expired exactly after 2 minutes! Whether I'm working with application or not.
These are my spring security beans:
<bean id="ConcurrentSessionFilterAdmin" class="org.springframework.security.web.session.ConcurrentSessionFilter">
<property name="sessionRegistry" ref="sessionRegistry"/>
<property name="logoutHandlers">
<list>
<ref bean = "logoutHandler"/>
</list>
</property>
<property name="expiredUrl" value="/admin/login.jsp?error=expiredURL"/>
</bean>
<bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" autowire="byType" />
<bean id="logoutHandler"
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
</bean>
<bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<property name="securityContextRepository" ref="securityContextRepository"/>
</bean>
<bean id="securityContextRepository"
class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
<property name="allowSessionCreation" value="false" />
</bean>
<bean id="logoutFilterAdmin"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/admin/login.jsp" />
<constructor-arg>
<list>
<ref bean="logoutHandler"/>
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/admin/j_spring_security_logout"></property>
</bean>
<bean id="usernamePasswordAuthenticationFilterAdmin"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="usernameParameter" value="j_username"/>
<property name="passwordParameter" value="j_password"/>
<property name="allowSessionCreation" value="false"/>
<property name="authenticationFailureHandler" ref="authenticationFailureHandlerAdmin"/>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandlerAdmin"/>
<property name="continueChainBeforeSuccessfulAuthentication" value="false"/>
<property name="filterProcessesUrl" value="/admin/j_spring_security_check"/>
<property name="sessionAuthenticationStrategy" ref="sessionAuthenticationStrategy"/>
</bean>
<bean id="authenticationFailureHandlerAdmin"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/admin/login.jsp?error=loginfailed" />
</bean>
<bean id="authenticationSuccessHandlerAdmin"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="requestCache" ref="requestCache"/>
<property name="defaultTargetUrl" value="/admin/index.html"/>
</bean>
<bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache"/>
<bean id="sessionAuthenticationStrategy"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<property name="maximumSessions" value="1" />
<property name="migrateSessionAttributes" value="true"/>
</bean>
<bean id="basicAuthenticationFilterAdmin"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationDetailsSource" ref="authenticationDetailsSource"/>
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<bean id="authenticationDetailsSource"
class="org.springframework.security.authentication.AuthenticationDetailsSourceImpl"/>
<bean id="requestCacheAwareFilter"
class="org.springframework.security.web.savedrequest.RequestCacheAwareFilter">
<constructor-arg ref="requestCache"/>
</bean>
<bean id="securityContextHolderAwareRequestFilter"
class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter">
<property name="rolePrefix" value="ROLE_"/>
</bean>
<bean id="anonymousAuthenticationFilter"
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<constructor-arg value="KEY"/>
</bean>
<bean id="sessionManagementFilterAdmin" class="org.springframework.security.web.session.SessionManagementFilter">
<constructor-arg ref="securityContextRepository"/>
<constructor-arg ref="sessionAuthenticationStrategy"/>
<property name="authenticationFailureHandler" ref="authenticationFailureHandlerAdmin"/>
<property name="invalidSessionStrategy" ref="invalidSessionStrategyAdmin"/>
</bean>
<bean id="invalidSessionStrategyAdmin"
class="org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy">
<constructor-arg value="/admin/login.jsp"/>
<property name="createNewSession" value="false"/>
</bean>
<bean id="exceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
<property name="accessDeniedHandler" ref="accessDeniedHandler" />
<property name="requestCache" ref="requestCache"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint">
</bean>
<bean id="accessDeniedHandler"
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
</bean>
<bean id="filterSecurityInterceptorAdmin"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource" ref="myFilterInvocationSecurityMetadataSource" />
</bean>
<bean id="myFilterInvocationSecurityMetadataSource" class="com.datx.security.model.MyFilterSecurityMetadataSource" autowire="byName" scope="prototype">
</bean>
After two minutes, I'm redirected to /admin/login.jsp?error=expiredURL which is set in the first bean configuration. (Which means session is expired)
The question is which of these beans are responsible for session expiration? What property haven't I set that causes this problem?
Spring Security relies on the underlying container, i.e. it's the container who manages session timeouts(please add information about the container you're using). However, I believe that web.xml settings usually should have a bigger priority if the server is Java EE compliant.
Also individual session timeouts can be tweaked dynamically by calling HttpSession.setMaxInactiveInterval() method, or the session can be invalidated by calling invalidate().
It's possible for Spring Security to invalidate session in some cases (for example, after logging in, the user gets a new HttpSession).
Also session invalidation can be caused by Spring Security concurrent-session control mechanism, for example if the max-sessions value is specified.
You can check when Spring Security invalidates the session by setting DEBUG logging level for org.springframework.security.* namespace, as Spring typically writes such info to the logger.

AccessDeniedException if using RoleHierarchyImpl

I am using role hierarchy in 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>
I am securing methods using protect-pointcut
<global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
<protect-pointcut expression="execution(* my.package.*(..))"
access="ROLE_GUEST"/>
</global-method-security>
However, I got AccessDeniedException if I login with user that has authority ROLE_USER. I have no issue if I specified protect-pointcut with access="ROLE_GUEST,ROLE_USER".
Am I missing some steps? FYI, I am using Spring 3.0.5.
Thanks.
Don't forget to add a WebExpressionVoter to be able to also use expressions in http element:
<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')" />
...
So I end up with an accessDecisionManager containing a role hierarchy voter and a WebExpressionVoter, both using the same 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>
(spring sec 3.1)
The nested beans are slightly wrong in jgraglia example above, and you don't need <ref bean="roleHierarchyVoter" /> because the hierarchy is handled in WebExpressionVoter. I'm doing this in Spring Security 4.0.0, but the code looks the same except you don't need use-expressions="true" because it's on by default.
I usually try and nest my beans as much as possible, so my code has no ref="" values unless required.
<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>
Have a look at bug report SEC-1163 and the comment below.
If you want basic support for role hierarchies, then use a RoleHierarchyVoter, instead of a RoleVoter.
So you need somethink like:
<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>

Resources