Pārlūkot izejas kodu

Migrate RememberMeConfigurerTests groovy->java

Issue: gh-4939
Eleftheria Stein 6 gadi atpakaļ
vecāks
revīzija
abe7da6b85

+ 0 - 290
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.groovy

@@ -1,290 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.config.annotation.web.configurers
-
-import org.springframework.security.core.userdetails.PasswordEncodedUser
-
-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.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.context.SecurityContext
-import org.springframework.security.core.userdetails.User
-import org.springframework.security.core.userdetails.UserDetailsService
-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
-
-/**
- * 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 {
-
-	def "rememberMe() null UserDetailsService provides meaningful error"() {
-		setup: "Load Config without UserDetailsService specified"
-			loadConfig(NullUserDetailsConfig)
-		when:
-			request.setCookies(createRememberMeCookie())
-			springSecurityFilterChain.doFilter(request, response, chain)
-		then: "A good error message is provided"
-			Exception success = thrown()
-			success.message.contains "UserDetailsService is required"
-	}
-
-	@EnableWebSecurity
-	static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.formLogin()
-					.and()
-				.rememberMe()
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			User user = PasswordEncodedUser.user();
-			DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
-			provider.userDetailsService = new InMemoryUserDetailsManager([user])
-			auth
-				.authenticationProvider(provider)
-		}
-	}
-
-	def "rememberMe ObjectPostProcessor"() {
-		setup:
-			AnyObjectPostProcessor opp = Mock()
-			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-			UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
-		when:
-			http
-				.rememberMe()
-					.userDetailsService(authenticationBldr.getDefaultUserDetailsService())
-					.and()
-				.build()
-
-		then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
-			1 * opp.postProcess(_ as RememberMeAuthenticationFilter) >> {RememberMeAuthenticationFilter o -> o}
-	}
-
-	def "invoke rememberMe twice does not reset"() {
-		setup:
-			AnyObjectPostProcessor opp = Mock()
-			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-			UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
-		when:
-			http
-				.rememberMe()
-					.userDetailsService(authenticationBldr.getDefaultUserDetailsService())
-					.and()
-				.rememberMe()
-		then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
-			http.getConfigurer(RememberMeConfigurer).userDetailsService != null
-	}
-
-
-	def "http/remember-me with Global AuthenticationManagerBuilder"() {
-		setup:
-			loadConfig(RememberMeConfig)
-		when: "login with remember me"
-			super.setup()
-			request.servletPath = "/login"
-			request.method = "POST"
-			request.parameters.username = ["user"] as String[]
-			request.parameters.password = ["password"] as String[]
-			request.parameters.'remember-me' = ["true"] as String[]
-			springSecurityFilterChain.doFilter(request,response,chain)
-			Cookie rememberMeCookie = getRememberMeCookie()
-		then: "response contains remember me cookie"
-			rememberMeCookie != null
-		when: "session expires"
-			super.setup()
-			request.setCookies(rememberMeCookie)
-			request.requestURI = "/abc"
-			springSecurityFilterChain.doFilter(request,response,chain)
-			MockHttpSession session = request.getSession()
-		then: "initialized to RememberMeAuthenticationToken"
-			SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
-			context.getAuthentication() instanceof RememberMeAuthenticationToken
-		when: "logout"
-			super.setup()
-			request.setSession(session)
-			super.setupCsrf()
-			request.setCookies(rememberMeCookie)
-			request.servletPath = "/logout"
-			request.method = "POST"
-			springSecurityFilterChain.doFilter(request,response,chain)
-			rememberMeCookie = getRememberMeCookie()
-		then: "logout cookie expired"
-			response.getRedirectedUrl() == "/login?logout"
-			rememberMeCookie.maxAge == 0
-		when: "use remember me after logout"
-			super.setup()
-			request.setCookies(rememberMeCookie)
-			request.requestURI = "/abc"
-			springSecurityFilterChain.doFilter(request,response,chain)
-		then: "sent to default login page"
-			response.getRedirectedUrl() == "http://localhost/login"
-	}
-
-	def "http/remember-me with cookie domain"() {
-		setup:
-			loadConfig(RememberMeCookieDomainConfig)
-		when:
-			super.setup()
-			request.servletPath = "/login"
-			request.method = "POST"
-			request.parameters.username = ["user"] as String[]
-			request.parameters.password = ["password"] as String[]
-			request.parameters.'remember-me' = ["true"] as String[]
-			springSecurityFilterChain.doFilter(request,response,chain)
-			Cookie rememberMeCookie = getRememberMeCookie()
-		then: "response contains remember me cookie"
-			rememberMeCookie != null
-			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 {
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.formLogin()
-					.and()
-				.rememberMe()
-		}
-
-		@Autowired
-		public void configureGlobal(AuthenticationManagerBuilder auth) {
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-		}
-	}
-
-	@EnableWebSecurity
-	static class RememberMeCookieDomainConfig extends WebSecurityConfigurerAdapter {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-					.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-					.formLogin()
-					.and()
-					.rememberMe()
-					.rememberMeCookieDomain("spring.io")
-		}
-
-		@Autowired
-		public void configureGlobal(AuthenticationManagerBuilder auth) {
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-		}
-	}
-
-	@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(PasswordEncodedUser.user());
-		}
-
-	}
-
-	Cookie createRememberMeCookie() {
-		MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
-		MockHttpServletResponse response = new MockHttpServletResponse()
-		super.setupCsrf("CSRF_TOKEN", request, response)
-
-		MockFilterChain chain = new MockFilterChain()
-		request.servletPath = "/login"
-		request.method = "POST"
-		request.parameters.username = ["user"] as String[]
-		request.parameters.password = ["password"] as String[]
-		request.parameters.'remember-me' = ["true"] as String[]
-		springSecurityFilterChain.doFilter(request, response, chain)
-		response.getCookie("remember-me")
-	}
-
-	Cookie getRememberMeCookie(String cookieName="remember-me") {
-		response.getCookie(cookieName)
-	}
-}

+ 376 - 0
config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java

@@ -0,0 +1,376 @@
+/*
+ * Copyright 2002-2019 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.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.config.annotation.web.configurers;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.security.authentication.RememberMeAuthenticationToken;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+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.config.test.SpringTestRule;
+import org.springframework.security.core.userdetails.PasswordEncodedUser;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
+import org.springframework.security.web.authentication.RememberMeServices;
+import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpSession;
+import java.util.Collections;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
+import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
+
+/**
+ * Tests for {@link RememberMeConfigurer}
+ *
+ * @author Rob Winch
+ * @author Eddú Meléndez
+ * @author Eleftheria Stein
+ */
+public class RememberMeConfigurerTests {
+
+	@Rule
+	public final SpringTestRule spring = new SpringTestRule();
+
+	@Autowired
+	MockMvc mvc;
+
+	@Test
+	public void postWhenNoUserDetailsServiceThenException() throws Exception {
+		this.spring.register(NullUserDetailsConfig.class).autowire();
+
+		assertThatThrownBy(() ->
+				mvc.perform(post("/login")
+						.param("username", "user")
+						.param("password", "password")
+						.param("remember-me", "true")
+						.with(csrf())))
+				.hasMessageContaining("UserDetailsService is required");
+	}
+
+	@EnableWebSecurity
+	static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			User user = (User) PasswordEncodedUser.user();
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+			provider.setUserDetailsService(new InMemoryUserDetailsManager(Collections.singletonList(user)));
+			// @formatter:off
+			auth
+				.authenticationProvider(provider);
+			// @formatter:on
+		}
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnRememberMeAuthenticationFilter() {
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor)
+				.postProcess(any(RememberMeAuthenticationFilter.class));
+	}
+
+	@EnableWebSecurity
+	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
+		static ObjectPostProcessor<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.rememberMe()
+					.userDetailsService(new AuthenticationManagerBuilder(objectPostProcessor).getDefaultUserDetailsService());
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor<Object> objectPostProcessor() {
+			return objectPostProcessor;
+		}
+	}
+
+	static class ReflectingObjectPostProcessor implements ObjectPostProcessor<Object> {
+		@Override
+		public <O> O postProcess(O object) {
+			return object;
+		}
+	}
+
+	@Test
+	public void rememberMeWhenInvokedTwiceThenUsesOriginalUserDetailsService() throws Exception {
+		when(DuplicateDoesNotOverrideConfig.userDetailsService.loadUserByUsername(anyString()))
+				.thenReturn(new User("user", "password", Collections.emptyList()));
+		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
+
+		this.mvc.perform(get("/")
+				.with(httpBasic("user", "password"))
+				.param("remember-me", "true"));
+
+		verify(DuplicateDoesNotOverrideConfig.userDetailsService).loadUserByUsername("user");
+	}
+
+	@EnableWebSecurity
+	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+		static UserDetailsService userDetailsService = mock(UserDetailsService.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic()
+					.and()
+				.rememberMe()
+					.userDetailsService(userDetailsService)
+					.and()
+				.rememberMe();
+			// @formatter:on
+		}
+
+		@Bean
+		public UserDetailsService userDetailsService() {
+			return new InMemoryUserDetailsManager(
+					User.withDefaultPasswordEncoder()
+							.username("user")
+							.password("password")
+							.roles("USER")
+							.build()
+			);
+		}
+	}
+
+	@Test
+	public void loginWhenRememberMeTrueThenRespondsWithRememberMeCookie() throws Exception {
+		this.spring.register(RememberMeConfig.class).autowire();
+
+		this.mvc.perform(post("/login")
+				.with(csrf())
+				.param("username", "user")
+				.param("password", "password")
+				.param("remember-me", "true"))
+				.andExpect(cookie().exists("remember-me"));
+	}
+
+	@Test
+	public void getWhenRememberMeCookieThenAuthenticationIsRememberMeAuthenticationToken() throws Exception {
+		this.spring.register(RememberMeConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(post("/login")
+				.with(csrf())
+				.param("username", "user")
+				.param("password", "password")
+				.param("remember-me", "true"))
+				.andReturn();
+		Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me");
+
+		this.mvc.perform(get("/abc")
+				.cookie(rememberMeCookie))
+				.andExpect(authenticated().withAuthentication(auth ->
+						assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class)));
+	}
+
+	@Test
+	public void logoutWhenRememberMeCookieThenAuthenticationIsRememberMeCookieExpired() throws Exception {
+		this.spring.register(RememberMeConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(post("/login")
+				.with(csrf())
+				.param("username", "user")
+				.param("password", "password")
+				.param("remember-me", "true"))
+				.andReturn();
+		Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me");
+		HttpSession session = mvcResult.getRequest().getSession();
+
+		this.mvc.perform(post("/logout")
+				.with(csrf())
+				.cookie(rememberMeCookie)
+				.session((MockHttpSession) session))
+				.andExpect(redirectedUrl("/login?logout"))
+				.andExpect(cookie().maxAge("remember-me", 0));
+	}
+
+	@Test
+	public void getWhenRememberMeCookieAndLoggedOutThenRedirectsToLogin() throws Exception {
+		this.spring.register(RememberMeConfig.class).autowire();
+
+		MvcResult loginMvcResult = this.mvc.perform(post("/login")
+				.with(csrf())
+				.param("username", "user")
+				.param("password", "password")
+				.param("remember-me", "true"))
+				.andReturn();
+		Cookie rememberMeCookie = loginMvcResult.getResponse().getCookie("remember-me");
+		HttpSession session = loginMvcResult.getRequest().getSession();
+		MvcResult logoutMvcResult = this.mvc.perform(post("/logout")
+				.with(csrf())
+				.cookie(rememberMeCookie)
+				.session((MockHttpSession) session))
+				.andReturn();
+		Cookie expiredRememberMeCookie = logoutMvcResult.getResponse().getCookie("remember-me");
+
+		this.mvc.perform(get("/abc")
+				.with(csrf())
+				.cookie(expiredRememberMeCookie))
+				.andExpect(redirectedUrl("http://localhost/login"));
+	}
+
+	@EnableWebSecurity
+	static class RememberMeConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe();
+			// @formatter:on
+		}
+
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+	}
+
+	@Test
+	public void loginWhenRememberMeTrueAndCookieDomainThenRememberMeCookieHasDomain() throws Exception {
+		this.spring.register(RememberMeCookieDomainConfig.class).autowire();
+
+		this.mvc.perform(post("/login")
+				.with(csrf())
+				.param("username", "user")
+				.param("password", "password")
+				.param("remember-me", "true"))
+				.andExpect(cookie().exists("remember-me"))
+				.andExpect(cookie().domain("remember-me", "spring.io"));
+	}
+
+	@EnableWebSecurity
+	static class RememberMeCookieDomainConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe()
+					.rememberMeCookieDomain("spring.io");
+			// @formatter:on
+		}
+
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+	}
+
+	@Test
+	public void configureWhenRememberMeCookieNameAndRememberMeServicesThenException() {
+		assertThatThrownBy(() -> this.spring.register(RememberMeCookieNameAndRememberMeServicesConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class)
+				.hasRootCauseInstanceOf(IllegalArgumentException.class)
+				.hasMessageContaining("Can not set rememberMeCookieName and custom rememberMeServices.");
+	}
+
+	@EnableWebSecurity
+	static class RememberMeCookieNameAndRememberMeServicesConfig extends WebSecurityConfigurerAdapter {
+		static RememberMeServices REMEMBER_ME = mock(RememberMeServices.class);
+
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe()
+					.rememberMeCookieName("SPRING_COOKIE_DOMAIN")
+					.rememberMeCookieDomain("spring.io")
+					.rememberMeServices(REMEMBER_ME);
+			// @formatter:on
+		}
+
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+	}
+}