瀏覽代碼

RememberMe JavaConfig Validation

Add validation when rememberMeServices and rememberMeCookieName are
provided

Fixes gh-3909
Eddú Meléndez 9 年之前
父節點
當前提交
87224f62e4

+ 15 - 2
config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java

@@ -79,12 +79,13 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera
  */
 public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
 		extends AbstractHttpConfigurer<RememberMeConfigurer<H>, H> {
+	public static final String REMEMBER_ME = "remember-me";
 	private AuthenticationSuccessHandler authenticationSuccessHandler;
 	private String key;
 	private RememberMeServices rememberMeServices;
 	private LogoutHandler logoutHandler;
-	private String rememberMeParameter = "remember-me";
-	private String rememberMeCookieName = "remember-me";
+	private String rememberMeParameter = REMEMBER_ME;
+	private String rememberMeCookieName = REMEMBER_ME;
 	private String rememberMeCookieDomain;
 	private PersistentTokenRepository tokenRepository;
 	private UserDetailsService userDetailsService;
@@ -244,6 +245,7 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
 	@SuppressWarnings("unchecked")
 	@Override
 	public void init(H http) throws Exception {
+		validateInput();
 		String key = getKey();
 		RememberMeServices rememberMeServices = getRememberMeServices(http, key);
 		http.setSharedObject(RememberMeServices.class, rememberMeServices);
@@ -273,6 +275,17 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>>
 		http.addFilter(rememberMeFilter);
 	}
 
+	/**
+	 * Validate rememberMeServices and rememberMeCookieName have not been set at
+	 * the same time.
+	 */
+	private void validateInput() {
+		if (this.rememberMeServices != null && this.rememberMeCookieName != REMEMBER_ME) {
+			throw new IllegalArgumentException("Can not set rememberMeCookieName " +
+					"and custom rememberMeServices.");
+		}
+	}
+
 	/**
 	 * Returns the HTTP parameter used to indicate to remember the user at time of login.
 	 * @return the HTTP parameter used to indicate to remember the user

+ 60 - 6
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.groovy

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,24 +17,27 @@ package org.springframework.security.config.annotation.web.configurers
 
 import javax.servlet.http.Cookie
 
+import org.springframework.beans.factory.BeanCreationException
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.mock.web.MockFilterChain
 import org.springframework.mock.web.MockHttpServletRequest
 import org.springframework.mock.web.MockHttpServletResponse
 import org.springframework.mock.web.MockHttpSession
 import org.springframework.security.authentication.RememberMeAuthenticationToken
-import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider
 import org.springframework.security.config.annotation.AnyObjectPostProcessor
 import org.springframework.security.config.annotation.BaseSpringSpec
+import org.springframework.security.config.annotation.ObjectPostProcessor
 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.core.authority.AuthorityUtils;
+import org.springframework.security.core.authority.AuthorityUtils
 import org.springframework.security.core.context.SecurityContext
-import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.User
 import org.springframework.security.core.userdetails.UserDetailsService
-import org.springframework.security.provisioning.InMemoryUserDetailsManager;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager
+import org.springframework.security.web.authentication.RememberMeServices
 import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter
 import org.springframework.security.web.context.HttpRequestResponseHolder
 import org.springframework.security.web.context.HttpSessionSecurityContextRepository
@@ -43,6 +46,7 @@ import org.springframework.security.web.context.HttpSessionSecurityContextReposi
  * Tests for RememberMeConfigurer that flex edge cases. {@link NamespaceRememberMeTests} demonstrate mapping of the XML namespace to Java Config.
  *
  * @author Rob Winch
+ * @author Eddú Meléndez
  */
 public class RememberMeConfigurerTests extends BaseSpringSpec {
 
@@ -155,7 +159,7 @@ public class RememberMeConfigurerTests extends BaseSpringSpec {
 			response.getRedirectedUrl() == "http://localhost/login"
 	}
 
-	def "http/remember-me with cookied domain"() {
+	def "http/remember-me with cookie domain"() {
 		setup:
 			loadConfig(RememberMeCookieDomainConfig)
 		when:
@@ -172,6 +176,29 @@ public class RememberMeConfigurerTests extends BaseSpringSpec {
 			rememberMeCookie.domain == "spring.io"
 	}
 
+	def "http/remember-me with cookie name and custom rememberMeServices throws BeanCreationException"() {
+		setup:
+		RememberMeCookieDomainCustomRememberMeServicesConfig.REMEMBER_ME = Mock(RememberMeServices)
+		when:
+		loadConfig(RememberMeCookieDomainCustomRememberMeServicesConfig)
+		then: "response contains remember me cookie"
+		def ex = thrown(BeanCreationException)
+		ex instanceof BeanCreationException
+	}
+
+	def "http/remember-me with cookie name and custom rememberMeServices throws IllegalArgumentException"() {
+		setup:
+		def httpSec = new HttpSecurity(Mock(ObjectPostProcessor), Mock(AuthenticationManagerBuilder), [:])
+		RememberMeConfigurer<HttpSecurity> config = new RememberMeConfigurer<HttpSecurity>();
+		config.rememberMeCookieName("COOKIE_NAME")
+		config.rememberMeServices(Mock(RememberMeServices))
+		when:
+		config.init(httpSec)
+		then:
+		IllegalArgumentException ex = thrown()
+		ex.message == 'Can not set rememberMeCookieName and custom rememberMeServices.'
+	}
+
 	@EnableWebSecurity
 	static class RememberMeConfig extends WebSecurityConfigurerAdapter {
 		protected void configure(HttpSecurity http) throws Exception {
@@ -213,6 +240,33 @@ public class RememberMeConfigurerTests extends BaseSpringSpec {
 		}
 	}
 
+	@EnableWebSecurity
+	static class RememberMeCookieDomainCustomRememberMeServicesConfig extends
+			WebSecurityConfigurerAdapter {
+		static RememberMeServices REMEMBER_ME
+
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+					.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+					.formLogin()
+					.and()
+					.rememberMe()
+					.rememberMeCookieName("SPRING_COOKIE_DOMAIN")
+					.rememberMeCookieDomain("spring.io")
+					.rememberMeServices(REMEMBER_ME);
+		}
+
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth
+					.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER");
+		}
+
+	}
+
 	Cookie createRememberMeCookie() {
 		MockHttpServletRequest request = new MockHttpServletRequest()
 		MockHttpServletResponse response = new MockHttpServletResponse()