How can I use intercept-method using its filters, not namespace?
-
18-06-2021 - |
Question
I'm trying to add some intercept-method in my application (using spring security) without namespaces.
So here is what I did:
First, I added a filter to filter-chain-map named "methodSecurityInterceptor" as you can see:
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/css/**" filters="none" />
<sec:filter-chain pattern="/images/**" filters="none" />
<sec:filter-chain pattern="/login.jsp*" filters="none" />
<sec:filter-chain pattern="/**"
filters="
ConcurrentSessionFilter,
securityContextPersistenceFilter,
sessionManagementFilter,
authenticationProcessingFilter,
exceptionTranslationFilter,
filterSecurityInterceptor,
methodSecurityInterceptor,
logoutFilter" />
</security:filter-chain-map>
</bean>
Then I introduced its bean like this:
<bean id="methodSecurityInterceptor"
class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource" ref="MyMethodMetdataSource">
</property>
</bean>
<bean id="MyMethodMetdataSource" class="com.datx.dao.MyMethodMetdataSource">
</bean>
And I have my MyMethodMetadataSource implemented like this:
public class MyMethodMetdataSource extends AbstractMethodSecurityMetadataSource{
@Override
public Collection<ConfigAttribute> getAttributes(Method arg0, Class<?> arg1) {
String url = arg0.getName();
List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();
attributes = getAttributesByURL2(url); //Here is my function which
//returns corresponding roles
return attributes;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
}
Apparently I am not allowed to use methodSecurityInterceptor as it's not a filter!
So what should I do?
I've read this but I have no idea how to use it with one of Spring AOP's proxying mechanisms!
So... Any idea?
Solution
The example I gave you before, is pretty much as simple as you can make it without using the namespace <global-method-security>
element.
Use Spring's AOP namespace with a pointcut matching the method(s) you want to protect:
<aop:config>
<aop:pointcut id='targetMethods' expression='execution(* org.springframework.security.TargetObject.*(..))'/>
<aop:advisor advice-ref='securityInterceptor' pointcut-ref='targetMethods' />
</aop:config>
and declare the security interceptor as a bean:
<bean id='target' class='org.springframework.security.TargetObject'/>
<bean id='securityInterceptor' class='org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor' autowire='byType' >
<property name='securityMetadataSource' ref="yourSecurityMetadataSource"/>
</bean>
External calls to that bean will then be routed through the security interceptor before the method is invoked.
I'd suggest you checkout the source and try running the test in a debugger to get a feel for how it works if you haven't use AOP before.
OTHER TIPS
Luckily I found the answer to this question.
One cannot use filters for intercept-method. So I suggest using proxies instead.
So here is the solution:
Change back the filter chain to its normal:
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/css/**" filters="none" />
<sec:filter-chain pattern="/images/**" filters="none" />
<sec:filter-chain pattern="/login.jsp*" filters="none" />
<sec:filter-chain pattern="/**"
filters="
ConcurrentSessionFilter,
securityContextPersistenceFilter,
sessionManagementFilter,
authenticationProcessingFilter,
exceptionTranslationFilter,
filterSecurityInterceptor,
logoutFilter" />
</security:filter-chain-map>
See what I did there? I removed the methodSecurityInterceptor.
Then add a proxy:
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>methodSecurityInterceptor</value> <!-- Responsible for checking roles and accesspaths -->
</list>
</property>
<property name="beanNames">
<list>
<value>Manager2</value> <!--The Class that I want to protect its methods -->
</list>
</property>
</bean>
Of course we have to add these beans to application context too:
<bean id="methodSecurityInterceptor"
class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource" ref="MyMethodMetdataSource">
</property>
</bean>
<bean id="MyMethodMetdataSource" class="com.datx.dao.MyMethodMetdataSource">
</bean>
Here we go :)
Now every method in Manager2.java will be checked for every method call.