7

I have to exclude one default filter from Spring Security stack. So all filters should work as usual. It seems like I find the way to do so, make custom FilterChainProxy:

public class CustomFilterChainProxy extends FilterChainProxy {

Logger LOGGER = Logger.getLogger(CustomFilterChainProxy.class);

public CustomFilterChainProxy() {
    super();
    LOGGER.debug("Run custom filter proxy");
    LOGGER.debug("String filters: " + this.toString());
}

public CustomFilterChainProxy(SecurityFilterChain chain) {
    super(chain);
    LOGGER.debug("Run custom filter proxy with chains");
}
}

As you see it have constructor which get list of filters, so I will be able to delete one filter from chain as I need and all the rest will work as usual. But I can`t make bean in security config for such constructor. If I use

<bean id="filterChainProxy" class="com.pkg.CustomFilterChainProxy">

it, of course build object with default constructor. Ok, I try to make bean with list of some filters:

<bean id="filterChainProxy" class="ru.olekstra.backoffice.util.CustomFilterChainProxy">
<constructor-arg>
    <list>
        <sec:filter-chain pattern="/**" 
        filters="BasicUserApprovalFilter" />
    </list>
</constructor-arg>
</bean>

But this wont compile, cause BasicUserApprovalFilter is unknown bean. So how could I exclude one filter from default filter stack? If my way with custom filter chain proxy is good decision, so how create bean with default filter chain?

sphinks
  • 3,048
  • 8
  • 39
  • 55

2 Answers2

5

It would probably help if you gave some more details on what the filter is you want to remove and why.

If you wish, you can use a BeanPostProcessor to modify the filter chain after it has been created. In a default namespace configuration, you can give the filter chain created by the <http> element a name:

<http name="myFilterChain">
   ...

This registers a bean of type SecurityFilterChain with this name. The FilterChainProxy is created from a list of these.

The post-processor would look something like:

public class SecurityFilterChainPostProcessor implements BeanPostProcessor {

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        if (beanName.equals("myFilterChain")) {
            DefaultSecurityFilterChain fc = (DefaultSecurityFilterChain)bean;
            List<Filter> filters = fc.getFilters();

            // Modify the filter list as you choose here.                
            List<Filter> newFilters = ...

            return new DefaultSecurityFilterChain(fc.getRequestMatcher(), newFilters);
        }

        return bean;
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

Then just register an instance of this bean in your application context and Spring will do the rest. That way you can avoid having to define all the Spring Security infrastructure filters as separate beans.

Update

Here is a link to a real-world example and its configuration.

Shaun the Sheep
  • 22,353
  • 1
  • 72
  • 100
  • I have such problem: http://stackoverflow.com/questions/14019472/spring-security-3-savedrequestawareauthenticationsuccesshandler-dont-make-diffe And after long search I found that request cache performed by EXCEPTION_TRANSLATION_FILTER, so as decision of this problem with cache I want to exclude filter. I can describe some more about caching problem if it would help spring project. – sphinks Jan 10 '13 at 07:55
  • And please show how to correctly set , cause it didn't work on my side (I just add this string and get error: Invalid content was found starting with element 'http'.), it seems I need more detailed manual for adding this bean to my config. – sphinks Jan 10 '13 at 08:42
  • Namespace configuration is fully explained in the reference manual and you'll find plenty of examples on SO. The "name" attribute only works with 3.1+, so make sure you are using an up to date XML schema (again copy the examples from the manual). – Shaun the Sheep Jan 10 '13 at 13:14
  • Removing the `ExceptionTranslationFilter` is a bad idea. I've posted a reply in the other thread. If you don't want to use cached requests, just configure authentication to always use the default target URL. – Shaun the Sheep Jan 10 '13 at 13:33
  • Luke, in other thread I wrote how I managed with this problems. But just for me, I just want to test this interesting code example. I implemented it as you wrote, in loop I pass all elements from filters to newFilters, except the first one, add some debug messages, but in logs still fired all 11 filters (but it should be only 10, cause I delete one filter). Also there is no logger (log4j) messages from this new calls. To see filter list I use situation that I describe in other thread (with getting old request from cache after log in). Can tell me what can be wrong? – sphinks Jan 14 '13 at 14:12
  • Proably not without access to the full code. If you post it on github or somewhere I could take a look. – Shaun the Sheep Jan 14 '13 at 14:40
  • I can publish my config+implementation SecurityFilterChainPostProcessor, will it be enought? – sphinks Jan 14 '13 at 15:13
  • I've added a link to a real example which adds a filter to the start of the chain. This is currently in use, so should provide you a working example which you can build and experiment with. – Shaun the Sheep Jan 14 '13 at 15:27
  • I managed to run you example. Just forget definition of bean: . Also removing RequestCacheAwareFilter also helps to avoid problem. Also I add detailed description of error, take a look at start post http://stackoverflow.com/questions/14019472/spring-security-3-savedrequestawareauthenticationsuccesshandler-doesnt-make-dif/14259095 I consider problem resolved, but may be this will be interesting for you. Fell free to ask for details. – sphinks Jan 15 '13 at 16:36
1

You can define you own filter chain via filter-chain-map tag in SpringSecurity config:

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <security:filter-chain-map>
       <sec:filter-chain pattern="/**"
            filters="
        ConcurrentSessionFilterAdmin, 
        securityContextPersistenceFilter, 
        logoutFilterAdmin, 
        .....
        anonymousAuthenticationFilter, 
        sessionManagementFilterAdmin, 
        exceptionTranslationFilter, 
        filterSecurityInterceptorAdmin,
        MonitoringFilter"/> 
    </security:filter-chain-map>
</bean>
Maksym Demidas
  • 7,707
  • 1
  • 29
  • 36
  • I have try this variant, but it seems doens't work: I left filters 7 filter as wrote in list, but in log I see that fired all 11 default filters: (FilterChainProxy.java:doFilter:318) /project/path at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter', ..., (FilterChainProxy.java:doFilter:318) /project/path at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'. So nothing change. – sphinks Jan 14 '13 at 13:57
  • Do you have springSecurityFilterChain in your web.xml for DelegatingFilterProxy? Do you use config element? – Maksym Demidas Jan 14 '13 at 14:09
  • Yes, I have such code: springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy in web.xml and use http element in spring security config. – sphinks Jan 14 '13 at 14:43
  • Try to debug DelegatingFilterProxy.initDelegate(...) method. It looks like at application sturtup DelegatingFilterProxy takes default filter-chain prepared by element instead of custom one. – Maksym Demidas Jan 14 '13 at 15:20
  • 1
    I am not sure that you can use and custom filter chain together. For me it looks like if you define your custom filter chain then you need to provide the rest of the beans provided by element manually (see [this example](https://open.jira.com/svn/PEBBLE/trunk/src/main/webapp/WEB-INF/applicationContext-security.xml), filterChainProxy and filterInvocationInterceptor beans). If you absolutelu want to use element then it may be better to use solution with BeanPostProcessor provided by @Luke Taylor – Maksym Demidas Jan 14 '13 at 15:34