RememberMe JavaConfig Validation

Add validation when rememberMeServices and rememberMeCookieName are
provided

Fixes gh-3909
This commit is contained in:
Eddú Meléndez 2016-06-02 23:44:14 +10:00 committed by Rob Winch
parent 8f880aea0e
commit 87224f62e4
2 changed files with 75 additions and 8 deletions

View File

@ -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

View File

@ -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()