diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java index 52b4596fec..633d72a7b0 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java @@ -20,7 +20,12 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.RequestCacheAwareFilter; +import org.springframework.security.web.util.AndRequestMatcher; import org.springframework.security.web.util.AntPathRequestMatcher; +import org.springframework.security.web.util.NegatedRequestMatcher; +import org.springframework.security.web.util.RequestMatcher; +import org.springframework.web.accept.ContentNegotiationStrategy; +import org.springframework.web.accept.HeaderContentNegotiationStrategy; /** * Adds request cache for Spring Security. Specifically this ensures that @@ -100,7 +105,17 @@ public final class RequestCacheConfigurer> exte return result; } HttpSessionRequestCache defaultCache = new HttpSessionRequestCache(); - defaultCache.setRequestMatcher(new AntPathRequestMatcher("/**", "GET")); + defaultCache.setRequestMatcher(createDefaultSavedRequestMatcher(http)); return defaultCache; } + + private RequestMatcher createDefaultSavedRequestMatcher(H http) { + ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); + if(contentNegotiationStrategy == null) { + contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); + } + RequestMatcher getRequests = new AntPathRequestMatcher("/**", "GET"); + RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.ico")); + return new AndRequestMatcher(getRequests,notFavIcon); + } } \ No newline at end of file diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.groovy index 71e13b4108..509df85411 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.groovy @@ -15,10 +15,16 @@ */ package org.springframework.security.config.annotation.web.configurers +import javax.servlet.http.HttpServletResponse + +import org.springframework.context.annotation.Configuration +import org.springframework.http.MediaType import org.springframework.security.config.annotation.AnyObjectPostProcessor import org.springframework.security.config.annotation.BaseSpringSpec import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter import org.springframework.security.web.savedrequest.RequestCache import org.springframework.security.web.savedrequest.RequestCacheAwareFilter @@ -57,4 +63,49 @@ class RequestCacheConfigurerTests extends BaseSpringSpec { then: http.getSharedObject(RequestCache) == RC } + + def "RequestCache disables faviocon.ico"() { + setup: + loadConfig(RequestCacheDefautlsConfig) + request.servletPath = "/favicon.ico" + request.requestURI = "/favicon.ico" + request.method = "GET" + when: "request favicon.ico" + springSecurityFilterChain.doFilter(request,response,chain) + then: "sent to the login page" + response.status == HttpServletResponse.SC_MOVED_TEMPORARILY + response.redirectedUrl == "http://localhost/login" + when: "authenticate successfully" + super.setupWeb(request.session) + request.servletPath = "/login" + request.setParameter("username","user") + request.setParameter("password","password") + request.method = "POST" + springSecurityFilterChain.doFilter(request,response,chain) + then: "sent to default URL since it was favicon.ico" + response.status == HttpServletResponse.SC_MOVED_TEMPORARILY + response.redirectedUrl == "/" + } + + @Configuration + @EnableWebSecurity + static class RequestCacheDefautlsConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .anyRequest().authenticated() + .and() + .formLogin() + } + + @Override + protected void registerAuthentication(AuthenticationManagerBuilder auth) + throws Exception { + auth + .inMemoryAuthentication() + .withUser("user").password("password").roles("USER") + } + } }