How to add multiple custom-filter in Spring Security 3?
I need add two custom filters for FORM_LOGIN_FILTER, e.g.
<开发者_StackOverflow中文版;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. myUsernamePasswordAuthenticationFilter2But above will cause configuration error. So, anyone knows how to write the right config? Thanks!
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" />
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.
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>
精彩评论