如何在Spring Security 3中添加多个自定义过滤器?

时间:2010-08-26 15:52:08

标签: java spring spring-security

我需要为FORM_LOGIN_FILTER添加两个自定义过滤器,例如

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

我期望过滤器序列是:
1.预定义FORM_LOGIN_FILTER
2. myUsernamePasswordAuthenticationFilter
3. myUsernamePasswordAuthenticationFilter2

但是上面会导致配置错误。 那么,谁知道如何编写正确的配置? 谢谢!

3 个答案:

答案 0 :(得分:38)

使用Spring CompositeFilter打包自定义过滤器列表,然后将该过滤器放在SecurityFilterChain上的相关位置。

E.g。像这样:

<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" />

答案 1 :(得分:6)

这样做:

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

这应该把它们放在你想要的地方。

答案 2 :(得分:0)

我解决了这个问题:

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);
  }

}

然后在上下文中我有:

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