Browse Source

SEC-2307: JavaConfig RequestCache ignores favicon.ico

Rob Winch 12 years ago
parent
commit
a888ddf8b3

+ 16 - 1
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<H extends HttpSecurityBuilder<H>> 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);
+    }
 }

+ 51 - 0
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")
+        }
+    }
 }