14

I need add two custom filters for FORM_LOGIN_FILTER, e.g.

<custom-filter after="FORM_LOGIN_FILTER" ref="myUsernamePasswordAuthenticationFilter" />
<custom-filter after="FORM_LOGIN_FILTER" ref="myUsernamePasswordAuthenticationFilter2" />

What I expect the filter sequences is:
1. Predefind FORM_LOGIN_FILTER
2. myUsernamePasswordAuthenticationFilter
3. myUsernamePasswordAuthenticationFilter2

But above will cause configuration error. So, anyone knows how to write the right config? Thanks!

3 Answers 3

56

Use Spring's CompositeFilter to wrap your custom filters list, and then put that filter on relevant position on SecurityFilterChain.

E.g. like this:

<bean id="customFilters" class="org.springframework.web.filter.CompositeFilter">
    <property name="filters">
        <list>
            <ref bean="myUsernamePasswordAuthenticationFilter"/>
            <ref bean="myUsernamePasswordAuthenticationFilter2"/>
        </list>
    </property>
</bean>
...
<custom-filter after="FORM_LOGIN_FILTER" ref="customFilters" />
Sign up to request clarification or add additional context in comments.

4 Comments

Glad there is a solution for this, but would be nice to allow bean refs instead of Enum values for before/after attributes
This is the right answer to the question and should e the chosen one. Thanks!
Correct answer, The filter beans can be configured with Request Matcher pattern as well
This must be the answer!
8

Do this:

<custom-filter after="FORM_LOGIN_FILTER" ref="myUsernamePasswordAuthenticationFilter" />
<custom-filter before="BASIC_AUTH_FILTER" ref="myUsernamePasswordAuthenticationFilter2" />

That should put them where you want them.

1 Comment

Thanks a lot! This could be a nice solution. But what if I want two add two or more custom filters between FORM_LOGIN_FILTER and BASIC_AUTH_FILTER? Is there any solution provided? Thanks again.
0

I solved it like this:

public class QmLoginFilterWrapper extends GenericFilterBean implements ApplicationEventPublisherAware,
    MessageSourceAware
{
  private static final Logger                          LOGGER     = LoggerFactory.getLogger(QmLoginFilterWrapper.class);

  private List<AbstractAuthenticationProcessingFilter> filterList = new ArrayList<AbstractAuthenticationProcessingFilter>();

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, final FilterChain chain) throws IOException,
      ServletException
  {
    FilterChain filterChain = new FilterChain() {

      @Override
      public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException
      {
        chain.doFilter(arg0, arg1);

      }
    };
    Vector<FilterChain> filterChains = new Vector<FilterChain>();
    filterChains.add(filterChain);
    if (LOGGER.isDebugEnabled())
    {
      LOGGER.debug("Filtering {} filters", filterList.size());
    }
    for (final GenericFilterBean filter : filterList)
    {
      final FilterChain lastChain = filterChains.lastElement();
      FilterChain loopChain = new FilterChain() {

        @Override
        public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException
        {
          if (LOGGER.isDebugEnabled())
          {
            LOGGER.debug("running filter {}", filter.getClass().getName());
          }
          filter.doFilter(arg0, arg1, lastChain);
        }
      };
      filterChains.add(loopChain);
    }
    filterChains.lastElement().doFilter(request, response);
  }

  @Override
  public void setMessageSource(MessageSource messageSource)
  {
    for (MessageSourceAware filter : filterList)
    {
      filter.setMessageSource(messageSource);
    }
  }

  @Override
  public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)
  {
    for (ApplicationEventPublisherAware applicationEventPublisherAware : filterList)
    {
      applicationEventPublisherAware.setApplicationEventPublisher(applicationEventPublisher);
    }
  }

  public List<AbstractAuthenticationProcessingFilter> getFilterList()
  {
    return filterList;
  }

  public void setFilterList(List<AbstractAuthenticationProcessingFilter> filterList)
  {
    this.filterList = filterList;
    Collections.reverse(this.filterList);
  }

}

Then in the context XML i have:

  <bean id="qmAuthFilter" class="com.qmplus.common.logon.QmLoginFilterWrapper">
    <property name="filterList">
      <list>
        <ref local="samlProcessingFilter" />
        <ref local="usernamePasswordAuthenticationFilter" />
      </list>
    </property>
  </bean>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.