Reputation: 129
I am using Spring Security 3.0.7 and my application is deployed on JBOSS.
I am setting up org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor for my application to add restrictions on invocation of certain methods in services layer. But for some reason the interceptor is not getting called and I am able to invoke all the methods from a user with a role, ROLE_USER. My security.xml looks like this:
<security:http auto-config='true' authentication-manager-ref="authenticationManager" use-expressions="true" request-matcher="ant" create-session="always"
entry-point-ref="authenticationEntryPoint" >
<security:intercept-url pattern="/login.jsp" access="permitAll" />
<security:intercept-url pattern="/configure/" access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=Authentication Failed!" default-target-url="/landing.do"
always-use-default-target="true" />
<security:logout invalidate-session="true" delete-cookies="true" />
<security:session-management>
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.jsp"/>
</security:session-management>
</security:http>
<security:method-security-metadata-source id="securityMetadataSource">
<security:protect method="com.services.CreateUserService.createUser" access="ROLE_ADMIN"/>
<security:protect method="com.services.DeleteUser.deleteUser" access="ROLE_ADMIN"/>
</security:method-security-metadata-source>
<security:global-method-security authentication-manager-ref="authenticationManager" access-decision-manager-ref="accessDecisionManager"
metadata-source-ref="securityMetadataSource" pre-post-annotations="disabled" secured-annotations="disabled" />
<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
<bean id="myRoleVoter" class="com.interceptors.MyRoleVoter" />
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager" >
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
</list>
</property>
</bean>
<bean id="accessDecisionManager" class="com.interceptors.MyAccessDecisionManager" p:allowIfAllAbstainDecisions="false" >
<property name="decisionVoters">
<list>
<ref local="myRoleVoter"/>
</list>
</property>
</bean>
<bean id="methodSecurity" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource" ref="securityMetadataSource" />
</bean>
The authentication part is working absolutely fine. However, my MethodSecurityInterceptor is never invoked and hence not even my AccessDecisionManager or RoleVoter.
If I add the reference of my accessDecisionManager in the first line, then my authentication layer stops working. All the requests pass to the AccessDecisionManager with the user as anonymous.
<security:http security="none" pattern="/login.jsp" />
<security:http auto-config='true' authentication-manager-ref="authenticationManager" access-decision-manager-ref="accessDecisionManager" use-expressions="true" request-matcher="ant" create-session="always"
entry-point-ref="authenticationEntryPoint" >
I know either I am missing some TINY configuration, but I am unable to find that configuration anywhere in the docs.
Upvotes: 1
Views: 3513
Reputation: 48753
Another usual reason why AOP MethodSecurityInterceptor
is not invoked - you miss cglib
or similar for byte code manipulation.
So only java.lang.reflect.Proxy
used and thus it is not possible to proxy private methods! Just make @Secured
methods public - and all be fine!
Upvotes: 1
Reputation: 129
I have figured out the solution. I have to define two authentication manager and one access decision manager. One authentication manager goes in my root context and would be used by the global method security to create the form login authentication mechanism.
The other authentication manager and the access decision manager goes in services context, where it would be used to create my custom method security interceptor.
applicationContext-Security.xml
<!-- The authentication manager responsible for authenticating the users -->
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager" >
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
</list>
</property>
</bean>
The context file for the services. service.security.xml
<!--we need a separate authentication manager for method security -->
<bean id="methodAuthenticationManager" class="org.springframework.security.authentication.ProviderManager" >
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
</list>
</property>
</bean>
<!--we need a separate accessDecisionManager for method security -->
<bean id="methodAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased" >
<property name="decisionVoters">
<list>
<ref local="myRoleVoter"/> <!-- the voter will decide weather methodInvocation is allowed or not -->
</list>
</property>
</bean>
<!-- The Method Security Interceptor to intercept all the calls to methods -->
<bean id="methodSecurityInterceptor" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="methodAuthenticationManager"/>
<property name="accessDecisionManager" ref="methodAccessDecisionManager"/>
<property name="securityMetadataSource" ref="swiftSecurityMethodMetadataSource" />
</bean>
<security:method-security-metadata-source id="securityMetadataSource">
<security:protect method="fullyQualifiedMethod" access="Administrator"/>
</security:method-security-metadata-source>
<security:global-method-security authentication-manager-ref="methodAuthenticationManager" access-decision-manager-ref="methodAccessDecisionManager"
metadata-source-ref="swiftSecurityMethodMetadataSource" jsr250-annotations="disabled" secured-annotations="disabled"/>
Upvotes: 1
Reputation: 17774
Possibly, you have declared your MethodSecurityInterceptor in your application root context, and expect it to work for the beans in the servlet context.
If you want global-method-security
to work in the servlet context, you should declare it explicitly in the servlet xml configuration.
It's a very common mistake to declare AOP interceptors in the wrong context, so please check that your service layer beans are not being created(for example by autoscanning) in the servlet context.
Upvotes: 1