Ver código fonte

RememberMeConfigTests groovy->java

Issue: gh-4939
Josh Cummings 7 anos atrás
pai
commit
950a314c9f
21 arquivos alterados com 1102 adições e 313 exclusões
  1. 0 312
      config/src/test/groovy/org/springframework/security/config/http/RememberMeConfigTests.groovy
  2. 378 0
      config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java
  3. 37 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-DefaultConfig.xml
  4. 39 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidity.xml
  5. 40 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidityWithDataSource.xml
  6. 39 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidityWithPersistentRepository.xml
  7. 39 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec1827.xml
  8. 39 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec2165.xml
  9. 40 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec742.xml
  10. 39 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-SecureCookie.xml
  11. 39 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-TokenValidity.xml
  12. 46 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithAuthenticationSuccessHandler.xml
  13. 41 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithDataSource.xml
  14. 33 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeCookie.xml
  15. 37 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeCookieAndServicesRef.xml
  16. 37 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeParameter.xml
  17. 37 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeParameterAndServicesRef.xml
  18. 47 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithServicesRef.xml
  19. 51 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithTokenRepository.xml
  20. 43 0
      config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithUserDetailsService.xml
  21. 1 1
      config/src/test/resources/org/springframework/security/config/http/userservice.xml

+ 0 - 312
config/src/test/groovy/org/springframework/security/config/http/RememberMeConfigTests.groovy

@@ -1,312 +0,0 @@
-/*
- * Copyright 2002-2015 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
- *
- *		http://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.http
-
-import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML
-
-import javax.sql.DataSource
-
-import org.springframework.beans.FatalBeanException
-import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
-import org.springframework.beans.factory.parsing.BeanDefinitionParsingException
-import org.springframework.security.TestDataSource
-import org.springframework.security.authentication.ProviderManager
-import org.springframework.security.authentication.RememberMeAuthenticationProvider
-import org.springframework.security.core.userdetails.MockUserDetailsService
-import org.springframework.security.util.FieldUtils
-import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
-import org.springframework.security.web.authentication.logout.LogoutFilter
-import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
-import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices
-import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl
-import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl
-import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices
-import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter
-import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices
-
-/**
- *
- * @author Luke Taylor
- * @author Rob Winch
- * @author Oliver Becker
- */
-class RememberMeConfigTests extends AbstractHttpConfigTests {
-
-	def rememberMeServiceWorksWithTokenRepoRef() {
-		httpAutoConfig () {
-			'remember-me'('token-repository-ref': 'tokenRepo')
-		}
-		bean('tokenRepo', CustomTokenRepository.class.name)
-
-		createAppContext(AUTH_PROVIDER_XML)
-
-		def rememberMeServices	= rememberMeServices()
-
-		expect:
-		rememberMeServices instanceof PersistentTokenBasedRememberMeServices
-		rememberMeServices.tokenRepository instanceof CustomTokenRepository
-		FieldUtils.getFieldValue(rememberMeServices, "useSecureCookie") == null
-	}
-
-	def rememberMeServiceWorksWithDataSourceRef() {
-		httpAutoConfig () {
-			'remember-me'('data-source-ref': 'ds')
-		}
-		bean('ds', TestDataSource.class.name, ['tokendb'])
-
-		createAppContext(AUTH_PROVIDER_XML)
-
-		def rememberMeServices	= rememberMeServices()
-
-		expect:
-		rememberMeServices instanceof PersistentTokenBasedRememberMeServices
-		rememberMeServices.tokenRepository instanceof JdbcTokenRepositoryImpl
-	}
-
-	def rememberMeServiceWorksWithAuthenticationSuccessHandlerRef() {
-		httpAutoConfig () {
-			'remember-me'('authentication-success-handler-ref': 'sh')
-		}
-		bean('sh', SimpleUrlAuthenticationSuccessHandler.class.name, ['/target'])
-
-		createAppContext(AUTH_PROVIDER_XML)
-
-		expect:
-		getFilter(RememberMeAuthenticationFilter.class).successHandler instanceof SimpleUrlAuthenticationSuccessHandler
-	}
-
-	def rememberMeServiceWorksWithExternalServicesImpl() {
-		httpAutoConfig () {
-			'remember-me'('key': "#{'our' + 'key'}", 'services-ref': 'rms')
-			csrf(disabled:true)
-		}
-		xml.'b:bean'(id: 'rms', 'class': TokenBasedRememberMeServices.class.name) {
-			'b:constructor-arg'(value: 'ourKey')
-			'b:constructor-arg'(ref: 'us')
-			'b:property'(name: 'tokenValiditySeconds', value: '5000')
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-
-		List logoutHandlers = FieldUtils.getFieldValue(getFilter(LogoutFilter.class), "handler").logoutHandlers;
-		Map ams = appContext.getBeansOfType(ProviderManager.class);
-		ProviderManager am = (ams.values() as List).find { it instanceof ProviderManager && it.providers.size() == 2}
-		RememberMeAuthenticationProvider rmp = am.providers.find { it instanceof RememberMeAuthenticationProvider}
-
-		expect:
-		rmp != null
-		5000 == FieldUtils.getFieldValue(rememberMeServices(), "tokenValiditySeconds")
-		// SEC-909
-		logoutHandlers.size() == 2
-		logoutHandlers.get(1) == rememberMeServices()
-		// SEC-1281
-		rmp.key == "ourkey"
-	}
-
-	def rememberMeAddsLogoutHandlerToLogoutFilter() {
-		httpAutoConfig () {
-			'remember-me'()
-			csrf(disabled:true)
-		}
-		createAppContext(AUTH_PROVIDER_XML)
-
-		def rememberMeServices = rememberMeServices()
-		List logoutHandlers = getFilter(LogoutFilter.class).handler.logoutHandlers
-
-		expect:
-		rememberMeServices
-		logoutHandlers.size() == 2
-		logoutHandlers.get(0) instanceof SecurityContextLogoutHandler
-		logoutHandlers.get(1) == rememberMeServices
-	}
-
-	def rememberMeTokenValidityIsParsedCorrectly() {
-		httpAutoConfig () {
-			'remember-me'('key': 'ourkey', 'token-validity-seconds':'10000')
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-
-		def rememberMeServices = rememberMeServices()
-		def rememberMeFilter = getFilter(RememberMeAuthenticationFilter.class)
-
-		expect:
-		rememberMeFilter.authenticationManager
-		rememberMeServices.key == 'ourkey'
-		rememberMeServices.tokenValiditySeconds == 10000
-		rememberMeServices.userDetailsService
-	}
-
-	def 'Remember-me token validity allows negative value for non-persistent implementation'() {
-		httpAutoConfig () {
-			'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1')
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-		expect:
-		rememberMeServices().tokenValiditySeconds == -1
-	}
-
-	def 'remember-me@token-validity-seconds denies for persistent implementation'() {
-		setup:
-			httpAutoConfig () {
-				'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'dataSource' : 'dataSource')
-			}
-			mockBean(DataSource)
-		when:
-			createAppContext(AUTH_PROVIDER_XML)
-		then:
-			thrown(FatalBeanException)
-	}
-
-	def 'SEC-2165: remember-me@token-validity-seconds allows property placeholders'() {
-		when:
-			httpAutoConfig () {
-				'remember-me'('key': 'ourkey', 'token-validity-seconds':'${security.rememberme.ttl}')
-			}
-			xml.'b:bean'(class: PropertyPlaceholderConfigurer.name) {
-				'b:property'(name:'properties', value:'security.rememberme.ttl=30')
-			}
-
-			createAppContext(AUTH_PROVIDER_XML)
-		then:
-			rememberMeServices().tokenValiditySeconds == 30
-	}
-
-	def rememberMeSecureCookieAttributeIsSetCorrectly() {
-		httpAutoConfig () {
-			'remember-me'('key': 'ourkey', 'use-secure-cookie':'true')
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-		expect:
-		FieldUtils.getFieldValue(rememberMeServices(), "useSecureCookie")
-	}
-
-	// SEC-1827
-	def rememberMeSecureCookieAttributeFalse() {
-		httpAutoConfig () {
-			'remember-me'('key': 'ourkey', 'use-secure-cookie':'false')
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-		expect: 'useSecureCookie is false'
-		FieldUtils.getFieldValue(rememberMeServices(), "useSecureCookie") == Boolean.FALSE
-	}
-
-	def 'Negative token-validity is rejected with persistent implementation'() {
-		when:
-		httpAutoConfig () {
-			'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'token-repository-ref': 'tokenRepo')
-		}
-		bean('tokenRepo', InMemoryTokenRepositoryImpl.class.name)
-		createAppContext(AUTH_PROVIDER_XML)
-
-		then:
-		BeanDefinitionParsingException e = thrown()
-	}
-
-	def 'Custom user service is supported'() {
-		when:
-		httpAutoConfig () {
-			'remember-me'('key': 'ourkey', 'token-validity-seconds':'-1', 'user-service-ref': 'userService')
-		}
-		bean('userService', MockUserDetailsService.class.name)
-		createAppContext(AUTH_PROVIDER_XML)
-
-		then: "Parses OK"
-		notThrown BeanDefinitionParsingException
-	}
-
-	// SEC-742
-	def rememberMeWorksWithoutBasicProcessingFilter() {
-		when:
-		xml.http () {
-			'form-login'('login-page': '/login.jsp', 'default-target-url': '/messageList.html' )
-			logout('logout-success-url': '/login.jsp')
-			anonymous(username: 'guest', 'granted-authority': 'guest')
-			'remember-me'()
-		}
-		createAppContext(AUTH_PROVIDER_XML)
-
-		then: "Parses OK"
-		notThrown BeanDefinitionParsingException
-	}
-
-	def 'Default remember-me-parameter is correct'() {
-		httpAutoConfig () {
-			'remember-me'()
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-		expect:
-		rememberMeServices().parameter == AbstractRememberMeServices.DEFAULT_PARAMETER
-	}
-
-	// SEC-2119
-	def 'Custom remember-me-parameter is supported'() {
-		httpAutoConfig () {
-			'remember-me'('remember-me-parameter': 'ourParam')
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-		expect:
-		rememberMeServices().parameter == 'ourParam'
-	}
-
-	def 'remember-me-parameter cannot be used together with services-ref'() {
-		when:
-		httpAutoConfig () {
-			'remember-me'('remember-me-parameter': 'ourParam', 'services-ref': 'ourService')
-		}
-		createAppContext(AUTH_PROVIDER_XML)
-		then:
-		BeanDefinitionParsingException e = thrown()
-	}
-
-	// SEC-2826
-	def 'Custom remember-me-cookie is supported'() {
-		httpAutoConfig () {
-			'remember-me'('remember-me-cookie': 'ourCookie')
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-		expect:
-		rememberMeServices().cookieName == 'ourCookie'
-	}
-
-	// SEC-2826
-	def 'remember-me-cookie cannot be used together with services-ref'() {
-		when:
-		httpAutoConfig () {
-			'remember-me'('remember-me-cookie': 'ourCookie', 'services-ref': 'ourService')
-		}
-
-		createAppContext(AUTH_PROVIDER_XML)
-		then:
-		BeanDefinitionParsingException e = thrown()
-		expect:
-		e.message == 'Configuration problem: services-ref can\'t be used in combination with attributes token-repository-ref,data-source-ref, user-service-ref, token-validity-seconds, use-secure-cookie, remember-me-parameter or remember-me-cookie\nOffending resource: null'
-	}
-
-	def rememberMeServices() {
-		getFilter(RememberMeAuthenticationFilter.class).getRememberMeServices()
-	}
-
-	static class CustomTokenRepository extends InMemoryTokenRepositoryImpl {
-
-	}
-}

+ 378 - 0
config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java

@@ -0,0 +1,378 @@
+/*
+ * Copyright 2002-2018 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
+ *
+ *      http://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.http;
+
+import java.util.Collections;
+import javax.servlet.http.Cookie;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.TestDataSource;
+import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.mockito.Mockito.atLeastOnce;
+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.web.authentication.rememberme.AbstractRememberMeServices.DEFAULT_PARAMETER;
+import static org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY;
+import static org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl.CREATE_TABLE_SQL;
+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;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ *
+ * @author Luke Taylor
+ * @author Rob Winch
+ * @author Oliver Becker
+ */
+public class RememberMeConfigTests {
+	private static final String CONFIG_LOCATION_PREFIX =
+			"classpath:org/springframework/security/config/http/RememberMeConfigTests";
+
+	@Autowired
+	MockMvc mvc;
+
+	@Rule
+	public final SpringTestRule spring = new SpringTestRule();
+
+	@Test
+	public void requestWithRememberMeWhenUsingCustomTokenRepositoryThenAutomaticallyReauthenticates()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithTokenRepository")).autowire();
+
+		MvcResult result = this.rememberAuthentication("user", "password")
+				.andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false))
+				.andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(get("/authenticated")
+				.cookie(cookie))
+				.andExpect(status().isOk());
+
+		JdbcTemplate template = this.spring.getContext().getBean(JdbcTemplate.class);
+		int count = template.queryForObject("select count(*) from persistent_logins", int.class);
+		assertThat(count).isEqualTo(1);
+	}
+
+	@Test
+	public void requestWithRememberMeWhenUsingCustomDataSourceThenAutomaticallyReauthenticates()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithDataSource")).autowire();
+
+		TestDataSource dataSource = this.spring.getContext().getBean(TestDataSource.class);
+		JdbcTemplate template = new JdbcTemplate(dataSource);
+		template.execute(CREATE_TABLE_SQL);
+
+		MvcResult result = this.rememberAuthentication("user", "password")
+				.andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false))
+				.andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(get("/authenticated")
+				.cookie(cookie))
+				.andExpect(status().isOk());
+
+		int count = template.queryForObject("select count(*) from persistent_logins", int.class);
+		assertThat(count).isEqualTo(1);
+	}
+
+	@Test
+	public void requestWithRememberMeWhenUsingAuthenticationSuccessHandlerThenInvokesHandler()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithAuthenticationSuccessHandler")).autowire();
+
+		TestDataSource dataSource = this.spring.getContext().getBean(TestDataSource.class);
+		JdbcTemplate template = new JdbcTemplate(dataSource);
+		template.execute(CREATE_TABLE_SQL);
+
+		MvcResult result = this.rememberAuthentication("user", "password")
+				.andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false))
+				.andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(get("/authenticated")
+				.cookie(cookie))
+				.andExpect(redirectedUrl("/target"));
+
+		int count = template.queryForObject("select count(*) from persistent_logins", int.class);
+		assertThat(count).isEqualTo(1);
+	}
+
+	@Test
+	public void requestWithRememberMeWhenUsingCustomRememberMeServicesThenAuthenticates()
+			throws Exception {
+		// SEC-1281 - using key with external services
+		this.spring.configLocations(this.xml("WithServicesRef")).autowire();
+
+		MvcResult result = this.rememberAuthentication("user", "password")
+				.andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false))
+				.andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 5000))
+				.andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(get("/authenticated")
+				.cookie(cookie))
+				.andExpect(status().isOk());
+
+		// SEC-909
+		this.mvc.perform(post("/logout")
+				.cookie(cookie)
+				.with(csrf()))
+				.andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 0))
+				.andReturn();
+	}
+
+	@Test
+	public void logoutWhenUsingRememberMeDefaultsThenCookieIsCancelled()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("DefaultConfig")).autowire();
+
+		MvcResult result = this.rememberAuthentication("user", "password").andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(post("/logout")
+				.cookie(cookie)
+				.with(csrf()))
+				.andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 0));
+	}
+
+	@Test
+	public void requestWithRememberMeWhenTokenValidityIsConfiguredThenCookieReflectsCorrectExpiration()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("TokenValidity")).autowire();
+
+		MvcResult result = this.rememberAuthentication("user", "password")
+				.andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 10000))
+				.andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(get("/authenticated")
+				.cookie(cookie))
+				.andExpect(status().isOk());
+	}
+
+	@Test
+	public void requestWithRememberMeWhenTokenValidityIsNegativeThenCookieReflectsCorrectExpiration()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("NegativeTokenValidity")).autowire();
+
+		this.rememberAuthentication("user", "password")
+				.andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, -1));
+	}
+
+
+	@Test
+	public void configureWhenUsingDataSourceAndANegativeTokenValidityThenThrowsWiringException() {
+		assertThatCode(() -> this.spring.configLocations(this.xml("NegativeTokenValidityWithDataSource")).autowire())
+			.isInstanceOf(FatalBeanException.class);
+	}
+
+	@Test
+	public void requestWithRememberMeWhenTokenValidityIsResolvedByPropertyPlaceholderThenCookieReflectsCorrectExpiration()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("Sec2165")).autowire();
+
+		this.rememberAuthentication("user", "password")
+				.andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 30));
+	}
+
+	@Test
+	public void requestWithRememberMeWhenUseSecureCookieIsTrueThenCookieIsSecure()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("SecureCookie")).autowire();
+
+		this.rememberAuthentication("user", "password")
+				.andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, true));
+	}
+
+	/**
+	 * SEC-1827
+	 */
+	@Test
+	public void requestWithRememberMeWhenUseSecureCookieIsFalseThenCookieIsNotSecure()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("Sec1827")).autowire();
+
+		this.rememberAuthentication("user", "password")
+				.andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false));
+	}
+
+	@Test
+	public void configureWhenUsingPersistentTokenRepositoryAndANegativeTokenValidityThenThrowsWiringException() {
+		assertThatCode(() -> this.spring.configLocations(this.xml("NegativeTokenValidityWithPersistentRepository")).autowire())
+				.isInstanceOf(BeanDefinitionParsingException.class);
+	}
+
+	@Test
+	public void requestWithRememberMeWhenUsingCustomUserDetailsServiceThenInvokesThisUserDetailsService()
+			throws Exception {
+		this.spring.configLocations(this.xml("WithUserDetailsService")).autowire();
+
+		UserDetailsService userDetailsService = this.spring.getContext().getBean(UserDetailsService.class);
+		when(userDetailsService.loadUserByUsername("user")).thenAnswer((invocation) ->
+				new User("user", "{noop}password", Collections.emptyList()));
+
+		MvcResult result = this.rememberAuthentication("user", "password").andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(get("/authenticated")
+				.cookie(cookie))
+				.andExpect(status().isOk());
+
+		verify(userDetailsService, atLeastOnce()).loadUserByUsername("user");
+	}
+
+	/**
+	 * SEC-742
+	 */
+	@Test
+	public void requestWithRememberMeWhenExcludingBasicAuthenticationFilterThenStillReauthenticates()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("Sec742")).autowire();
+
+		MvcResult result =
+				this.mvc.perform(login("user", "password")
+						.param("remember-me", "true")
+						.with(csrf()))
+						.andExpect(redirectedUrl("/messageList.html"))
+						.andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(get("/authenticated")
+				.cookie(cookie))
+				.andExpect(status().isOk());
+	}
+
+	/**
+	 * SEC-2119
+	 */
+	@Test
+	public void requestWithRememberMeWhenUsingCustomRememberMeParameterThenReauthenticates()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithRememberMeParameter")).autowire();
+
+		MvcResult result =
+				this.mvc.perform(login("user", "password")
+						.param("custom-remember-me-parameter", "true")
+						.with(csrf()))
+						.andExpect(redirectedUrl("/"))
+						.andReturn();
+
+		Cookie cookie = rememberMeCookie(result);
+
+		this.mvc.perform(get("/authenticated")
+				.cookie(cookie))
+				.andExpect(status().isOk());
+	}
+
+	@Test
+	public void configureWhenUsingRememberMeParameterAndServicesRefThenThrowsWiringException() {
+		assertThatCode(() -> this.spring.configLocations(this.xml("WithRememberMeParameterAndServicesRef")).autowire())
+				.isInstanceOf(BeanDefinitionParsingException.class);
+	}
+
+	/**
+	 * SEC-2826
+	 */
+	@Test
+	public void authenticateWhenUsingCustomRememberMeCookieNameThenIssuesCookieWithThatName()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithRememberMeCookie")).autowire();
+
+		this.rememberAuthentication("user", "password")
+				.andExpect(cookie().exists("custom-remember-me-cookie"));
+	}
+
+	/**
+	 * SEC-2826
+	 */
+	@Test
+	public void configureWhenUsingRememberMeCookieAndServicesRefThenThrowsWiringException() {
+		assertThatCode(() -> this.spring.configLocations(this.xml("WithRememberMeCookieAndServicesRef")).autowire())
+				.isInstanceOf(BeanDefinitionParsingException.class)
+				.hasMessageContaining("Configuration problem: services-ref can't be used in combination with attributes " +
+						"token-repository-ref,data-source-ref, user-service-ref, token-validity-seconds, use-secure-cookie, " +
+						"remember-me-parameter or remember-me-cookie");
+	}
+
+	@RestController
+	static class BasicController {
+		@GetMapping("/authenticated")
+		String ok() {
+			return "ok";
+		}
+	}
+
+	private ResultActions rememberAuthentication(String username, String password)
+			throws Exception {
+
+		return this.mvc.perform(login(username, password)
+				.param(DEFAULT_PARAMETER, "true")
+				.with(csrf()))
+				.andExpect(redirectedUrl("/"));
+	}
+
+	private static MockHttpServletRequestBuilder login(String username, String password) {
+		return post("/login").param("username", username).param("password", password);
+	}
+
+	private static Cookie rememberMeCookie(MvcResult result) {
+		return result.getResponse().getCookie("remember-me");
+	}
+
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+}

+ 37 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-DefaultConfig.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 39 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidity.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me
+				key="ourkey"
+				token-validity-seconds="-1"/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 40 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidityWithDataSource.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me
+				key="ourkey"
+				token-validity-seconds="-1"
+				data-source-ref="dataSource"/>
+	</http>
+
+	<b:bean name="dataSource" class="org.springframework.security.TestDataSource">
+		<b:constructor-arg value="tokendb"/>
+	</b:bean>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 39 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-NegativeTokenValidityWithPersistentRepository.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me
+				key="ourkey"
+				token-validity-seconds="-1"
+				token-repository-ref="tokenRepository"/>
+	</http>
+
+	<b:bean name="tokenRepository"
+			class="org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 39 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec1827.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me
+				key="ourkey"
+				use-secure-cookie="false"/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 39 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec2165.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me
+				key="ourkey"
+				token-validity-seconds="${security.rememberme.ttl}"/>
+	</http>
+
+	<b:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+		<b:property name="properties" value="security.rememberme.ttl=30"/>
+	</b:bean>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 40 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-Sec742.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http>
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<form-login login-page="/login.jsp" default-target-url="/messageList.html"/>
+		<logout logout-success-url="/login.jsp"/>
+		<anonymous username="guest" granted-authority="guest"/>
+		<remember-me/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 39 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-SecureCookie.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me
+				key="ourkey"
+				use-secure-cookie="true"/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 39 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-TokenValidity.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me
+				key="ourkey"
+				token-validity-seconds="10000"/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 46 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithAuthenticationSuccessHandler.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me authentication-success-handler-ref="authenticationSuccessHandler"
+				data-source-ref="dataSource"/>
+	</http>
+
+	<b:bean name="authenticationSuccessHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
+		<b:constructor-arg value="/target"/>
+	</b:bean>
+
+	<b:bean name="dataSource" class="org.springframework.security.TestDataSource">
+		<b:constructor-arg value="tokendb"/>
+	</b:bean>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 41 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithDataSource.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me data-source-ref="dataSource"/>
+	</http>
+
+	<b:bean name="dataSource" class="org.springframework.security.TestDataSource">
+		<b:constructor-arg value="tokendb"/>
+	</b:bean>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 33 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeCookie.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me remember-me-cookie="custom-remember-me-cookie"/>
+	</http>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 37 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeCookieAndServicesRef.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me remember-me-cookie="custom-remember-me-cookie" services-ref="services"/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 37 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeParameter.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me remember-me-parameter="custom-remember-me-parameter"/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 37 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithRememberMeParameterAndServicesRef.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me remember-me-parameter="custom-remember-me-parameter" services-ref="services"/>
+	</http>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 47 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithServicesRef.xml

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+
+		<!-- SEC-1281 - using key with external services -->
+		<remember-me
+				key="#{'our' + 'key'}"
+				services-ref="services"/>
+	</http>
+
+	<b:bean name="services" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
+		<b:constructor-arg value="ourkey"/>
+		<b:constructor-arg ref="us"/>
+		<b:property name="tokenValiditySeconds" value="5000"/>
+	</b:bean>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 51 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithTokenRepository.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me token-repository-ref="tokenRepository"/>
+	</http>
+
+	<b:bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+		<b:constructor-arg>
+			<b:bean name="dataSource" class="org.springframework.security.TestDataSource">
+				<b:constructor-arg value="tokendb"/>
+			</b:bean>
+		</b:constructor-arg>
+	</b:bean>
+
+	<b:bean name="tokenRepository"
+			class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
+		<b:property name="createTableOnStartup" value="true"/>
+		<b:property name="jdbcTemplate" ref="jdbcTemplate"/>
+	</b:bean>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 43 - 0
config/src/test/resources/org/springframework/security/config/http/RememberMeConfigTests-WithUserDetailsService.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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
+  ~
+  ~       http://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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated" access="authenticated"/>
+		<remember-me user-service-ref="userDetailsService"/>
+	</http>
+
+	<authentication-manager>
+		<authentication-provider user-service-ref="userDetailsService"/>
+	</authentication-manager>
+
+	<b:bean name="userDetailsService" class="org.mockito.Mockito" factory-method="mock">
+		<b:constructor-arg value="org.springframework.security.core.userdetails.UserDetailsService"/>
+	</b:bean>
+
+	<b:bean
+		name="basicController"
+		class="org.springframework.security.config.http.RememberMeConfigTests.BasicController"/>
+</b:beans>

+ 1 - 1
config/src/test/resources/org/springframework/security/config/http/userservice.xml

@@ -23,7 +23,7 @@
 			http://www.springframework.org/schema/security/spring-security.xsd
 			http://www.springframework.org/schema/beans
 			http://www.springframework.org/schema/beans/spring-beans.xsd">
-	<user-service>
+	<user-service id="us">
 		<user name="user" password="{noop}password" authorities="ROLE_USER"/>
 		<user name="admin" password="{noop}password" authorities="ROLE_ADMIN"/>
 	</user-service>