SecurityMockMvcConfigurer Honors Filter Order
Fixes gh-7265
This commit is contained in:
+87
-8
@@ -16,6 +16,11 @@
|
||||
package org.springframework.security.test.web.servlet.setup;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
@@ -23,6 +28,8 @@ import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurerAdapter;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.testSecurityContext;
|
||||
|
||||
/**
|
||||
@@ -34,12 +41,13 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock
|
||||
* @since 4.0
|
||||
*/
|
||||
final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter {
|
||||
private Filter springSecurityFilterChain;
|
||||
private final DelegateFilter delegateFilter;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*/
|
||||
SecurityMockMvcConfigurer() {
|
||||
this.delegateFilter = new DelegateFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,30 +55,101 @@ final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter {
|
||||
* @param springSecurityFilterChain the {@link javax.servlet.Filter} to use
|
||||
*/
|
||||
SecurityMockMvcConfigurer(Filter springSecurityFilterChain) {
|
||||
this.springSecurityFilterChain = springSecurityFilterChain;
|
||||
this.delegateFilter = new DelegateFilter(springSecurityFilterChain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder) {
|
||||
builder.addFilters(this.delegateFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestPostProcessor beforeMockMvcCreated(
|
||||
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
|
||||
String securityBeanId = BeanIds.SPRING_SECURITY_FILTER_CHAIN;
|
||||
if (this.springSecurityFilterChain == null
|
||||
if (getSpringSecurityFilterChain() == null
|
||||
&& context.containsBean(securityBeanId)) {
|
||||
this.springSecurityFilterChain = context.getBean(securityBeanId,
|
||||
Filter.class);
|
||||
setSpringSecurityFitlerChain(context.getBean(securityBeanId,
|
||||
Filter.class));
|
||||
}
|
||||
|
||||
if (this.springSecurityFilterChain == null) {
|
||||
if (getSpringSecurityFilterChain() == null) {
|
||||
throw new IllegalStateException(
|
||||
"springSecurityFilterChain cannot be null. Ensure a Bean with the name "
|
||||
+ securityBeanId
|
||||
+ " implementing Filter is present or inject the Filter to be used.");
|
||||
}
|
||||
|
||||
builder.addFilters(this.springSecurityFilterChain);
|
||||
// This is used by other test support to obtain the FilterChainProxy
|
||||
context.getServletContext().setAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN,
|
||||
this.springSecurityFilterChain);
|
||||
getSpringSecurityFilterChain());
|
||||
|
||||
return testSecurityContext();
|
||||
}
|
||||
|
||||
private void setSpringSecurityFitlerChain(Filter filter) {
|
||||
this.delegateFilter.setDelegate(filter);
|
||||
}
|
||||
|
||||
private Filter getSpringSecurityFilterChain() {
|
||||
return this.delegateFilter.delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows adding in {@link #afterConfigurerAdded(ConfigurableMockMvcBuilder)} to preserve Filter order and then
|
||||
* lazily set the delegate in {@link #beforeMockMvcCreated(ConfigurableMockMvcBuilder, WebApplicationContext)}.
|
||||
*
|
||||
* {@link org.springframework.web.filter.DelegatingFilterProxy} is not used because it is not easy to lazily set
|
||||
* the delegate or get the delegate which is necessary for the test infrastructure.
|
||||
*/
|
||||
static class DelegateFilter implements Filter {
|
||||
|
||||
private Filter delegate;
|
||||
|
||||
DelegateFilter() {
|
||||
}
|
||||
|
||||
DelegateFilter(Filter delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
void setDelegate(Filter delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
Filter getDelegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
this.delegate.init(filterConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
this.delegate.doFilter(request, response, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.delegate.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.delegate.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return this.delegate.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.delegate.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user