parent
d2a37cb1d6
commit
519c15efb3
|
@ -38,6 +38,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
|
|||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
|
@ -78,6 +79,10 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
|||
*/
|
||||
public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
||||
AbstractHttpConfigurer<HttpBasicConfigurer<B>, B> {
|
||||
|
||||
private static final RequestHeaderRequestMatcher X_REQUESTED_WITH = new RequestHeaderRequestMatcher("X-Requested-With",
|
||||
"XMLHttpRequest");
|
||||
|
||||
private static final String DEFAULT_REALM = "Realm";
|
||||
|
||||
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||
|
@ -93,8 +98,7 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
|||
realmName(DEFAULT_REALM);
|
||||
|
||||
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<RequestMatcher, AuthenticationEntryPoint>();
|
||||
entryPoints.put(new RequestHeaderRequestMatcher("X-Requested-With",
|
||||
"XMLHttpRequest"), new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
|
||||
entryPoints.put(X_REQUESTED_WITH, new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
|
||||
|
||||
DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(
|
||||
entryPoints);
|
||||
|
@ -157,6 +161,7 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
|||
if (contentNegotiationStrategy == null) {
|
||||
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
|
||||
}
|
||||
|
||||
MediaTypeRequestMatcher restMatcher = new MediaTypeRequestMatcher(
|
||||
contentNegotiationStrategy, MediaType.APPLICATION_ATOM_XML,
|
||||
MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON,
|
||||
|
@ -167,9 +172,11 @@ public final class HttpBasicConfigurer<B extends HttpSecurityBuilder<B>> extends
|
|||
RequestMatcher notHtmlMatcher = new NegatedRequestMatcher(
|
||||
new MediaTypeRequestMatcher(contentNegotiationStrategy,
|
||||
MediaType.TEXT_HTML));
|
||||
RequestMatcher preferredMatcher = new AndRequestMatcher(
|
||||
RequestMatcher restNotHtmlMatcher = new AndRequestMatcher(
|
||||
Arrays.<RequestMatcher>asList(notHtmlMatcher, restMatcher));
|
||||
|
||||
RequestMatcher preferredMatcher = new OrRequestMatcher(Arrays.asList(X_REQUESTED_WITH, restNotHtmlMatcher));
|
||||
|
||||
registerDefaultEntryPoint(http, preferredMatcher);
|
||||
registerDefaultLogoutSuccessHandler(http, preferredMatcher);
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ class ExceptionHandlingConfigurerTests extends BaseSpringSpec {
|
|||
DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
|
||||
then:
|
||||
def entryPoints = delegateEntryPoint.entryPoints.keySet() as List
|
||||
entryPoints[0].requestMatchers[1].contentNegotiationStrategy.class == HeaderContentNegotiationStrategy
|
||||
entryPoints[0].requestMatchers[1].requestMatchers[1].contentNegotiationStrategy.class == HeaderContentNegotiationStrategy
|
||||
entryPoints[1].requestMatchers[1].contentNegotiationStrategy.class == HeaderContentNegotiationStrategy
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ class ExceptionHandlingConfigurerTests extends BaseSpringSpec {
|
|||
then:
|
||||
def entryPoints = delegateEntryPoint.entryPoints.keySet() as List
|
||||
entryPoints[0].requestMatchers[1].contentNegotiationStrategy == OverrideContentNegotiationStrategySharedObjectConfig.CNS
|
||||
entryPoints[1].requestMatchers[1].contentNegotiationStrategy == OverrideContentNegotiationStrategySharedObjectConfig.CNS
|
||||
entryPoints[1].requestMatchers[1].requestMatchers[1].contentNegotiationStrategy == OverrideContentNegotiationStrategySharedObjectConfig.CNS
|
||||
}
|
||||
|
||||
def "Override ContentNegotiationStrategy with @Bean"() {
|
||||
|
|
|
@ -232,4 +232,23 @@ class LogoutConfigurerTests extends BaseSpringSpec {
|
|||
@EnableWebSecurity
|
||||
static class LogoutHandlerContentNegotiationForChrome extends WebSecurityConfigurerAdapter {
|
||||
}
|
||||
|
||||
// gh-3997
|
||||
def "LogoutConfigurer for XMLHttpRequest is 204"() {
|
||||
setup:
|
||||
loadConfig(LogoutXMLHttpRequestConfig)
|
||||
when:
|
||||
login()
|
||||
request.method = 'POST'
|
||||
request.servletPath = '/logout'
|
||||
request.addHeader('Accept', 'text/html,application/json')
|
||||
request.addHeader('X-Requested-With', 'XMLHttpRequest')
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
response.status == 204
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class LogoutXMLHttpRequestConfig extends WebSecurityConfigurerAdapter {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue