Polish SpringSessionRememberMeServices
* Move to ~.security.web.authentication package * Add documentation * Use getBeanNamesForType to avoid eager bean initialization * Remove rememberMeCookieMaxAge because it must be Integer.MAX_VALUE since cookie is only written at the creation of the session * Change from parameter to rememberMeParameterName Issue gh-189
This commit is contained in:
@@ -33,7 +33,7 @@ import org.springframework.session.ExpiringSession;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.events.SessionCreatedEvent;
|
||||
import org.springframework.session.events.SessionDestroyedEvent;
|
||||
import org.springframework.session.security.SpringSessionRememberMeServices;
|
||||
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
|
||||
import org.springframework.session.web.http.CookieHttpSessionStrategy;
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
@@ -42,6 +42,7 @@ import org.springframework.session.web.http.MultiHttpSessionStrategy;
|
||||
import org.springframework.session.web.http.SessionEventHttpSessionListenerAdapter;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Configures the basics for setting up Spring Session in a web environment. In order to
|
||||
@@ -138,10 +139,12 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
if (ClassUtils.isPresent("org.springframework.security.web.authentication." +
|
||||
"RememberMeServices", null)) {
|
||||
this.usesSpringSessionRememberMeServices = !applicationContext
|
||||
.getBeansOfType(SpringSessionRememberMeServices.class).isEmpty();
|
||||
if (ClassUtils.isPresent(
|
||||
"org.springframework.security.web.authentication.RememberMeServices",
|
||||
null)) {
|
||||
this.usesSpringSessionRememberMeServices = !ObjectUtils
|
||||
.isEmpty(applicationContext
|
||||
.getBeanNamesForType(SpringSessionRememberMeServices.class));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.security;
|
||||
package org.springframework.session.security.web.authentication;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -34,7 +35,8 @@ import org.springframework.util.Assert;
|
||||
* @author Vedran Pavic
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class SpringSessionRememberMeServices implements RememberMeServices {
|
||||
public class SpringSessionRememberMeServices
|
||||
implements RememberMeServices, LogoutHandler {
|
||||
|
||||
/**
|
||||
* Remember-me login request attribute name.
|
||||
@@ -42,13 +44,14 @@ public class SpringSessionRememberMeServices implements RememberMeServices {
|
||||
public static final String REMEMBER_ME_LOGIN_ATTR = SpringSessionRememberMeServices.class
|
||||
.getName() + "REMEMBER_ME_LOGIN_ATTR";
|
||||
|
||||
private static final String DEFAULT_PARAMETER = "remember-me";
|
||||
private static final String DEFAULT_REMEMBERME_PARAMETER = "remember-me";
|
||||
|
||||
private static final int THIRTY_DAYS_SECONDS = 2592000;
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SpringSessionRememberMeServices.class);
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(SpringSessionRememberMeServices.class);
|
||||
|
||||
private String parameter = DEFAULT_PARAMETER;
|
||||
private String rememberMeParameterName = DEFAULT_REMEMBERME_PARAMETER;
|
||||
|
||||
private boolean alwaysRemember;
|
||||
|
||||
@@ -59,17 +62,15 @@ public class SpringSessionRememberMeServices implements RememberMeServices {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void loginFail(HttpServletRequest request, HttpServletResponse response) {
|
||||
logger.debug("Interactive login attempt was unsuccessful.");
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
session.invalidate();
|
||||
}
|
||||
public final void loginFail(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
logout(request);
|
||||
}
|
||||
|
||||
public final void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication successfulAuthentication) {
|
||||
if (!this.alwaysRemember && !rememberMeRequested(request, this.parameter)) {
|
||||
public final void loginSuccess(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication successfulAuthentication) {
|
||||
if (!this.alwaysRemember
|
||||
&& !rememberMeRequested(request, this.rememberMeParameterName)) {
|
||||
logger.debug("Remember-me login not requested.");
|
||||
return;
|
||||
}
|
||||
@@ -96,8 +97,8 @@ public class SpringSessionRememberMeServices implements RememberMeServices {
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Did not send remember-me cookie (principal did not set " +
|
||||
"parameter '" + parameter + "')");
|
||||
logger.debug("Did not send remember-me cookie (principal did not set "
|
||||
+ "parameter '" + parameter + "')");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -106,11 +107,12 @@ public class SpringSessionRememberMeServices implements RememberMeServices {
|
||||
* Set the name of the parameter which should be checked for to see if a remember-me
|
||||
* has been requested during a login request. This should be the same name you assign
|
||||
* to the checkbox in your login form.
|
||||
* @param parameter the request parameter
|
||||
* @param rememberMeParameterName the request parameter
|
||||
*/
|
||||
public void setParameter(String parameter) {
|
||||
Assert.hasText(parameter, "Parameter name cannot be empty or null");
|
||||
this.parameter = parameter;
|
||||
public void setRememberMeParameterName(String rememberMeParameterName) {
|
||||
Assert.hasText(rememberMeParameterName,
|
||||
"rememberMeParameterName cannot be empty or null");
|
||||
this.rememberMeParameterName = rememberMeParameterName;
|
||||
}
|
||||
|
||||
public void setAlwaysRemember(boolean alwaysRemember) {
|
||||
@@ -121,4 +123,16 @@ public class SpringSessionRememberMeServices implements RememberMeServices {
|
||||
this.validitySeconds = validitySeconds;
|
||||
}
|
||||
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) {
|
||||
logout(request);
|
||||
}
|
||||
|
||||
private void logout(HttpServletRequest request) {
|
||||
logger.debug("Interactive login attempt was unsuccessful.");
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
session.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,8 +55,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
|
||||
private String rememberMeRequestAttribute;
|
||||
|
||||
private int rememberMeCookieMaxAge = Integer.MAX_VALUE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@@ -115,9 +113,11 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
if ("".equals(requestedCookieValue)) {
|
||||
sessionCookie.setMaxAge(0);
|
||||
}
|
||||
else if (this.rememberMeRequestAttribute != null &&
|
||||
request.getAttribute(this.rememberMeRequestAttribute) != null) {
|
||||
sessionCookie.setMaxAge(this.rememberMeCookieMaxAge);
|
||||
else if (this.rememberMeRequestAttribute != null
|
||||
&& request.getAttribute(this.rememberMeRequestAttribute) != null) {
|
||||
// the cookie is only written at time of session creation, so we rely on
|
||||
// session expiration rather than cookie expiration if remember me is enabled
|
||||
sessionCookie.setMaxAge(Integer.MAX_VALUE);
|
||||
}
|
||||
else {
|
||||
sessionCookie.setMaxAge(this.cookieMaxAge);
|
||||
@@ -209,10 +209,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
* @param cookieMaxAge the maxAge property of the Cookie
|
||||
*/
|
||||
public void setCookieMaxAge(int cookieMaxAge) {
|
||||
if (cookieMaxAge > this.rememberMeCookieMaxAge) {
|
||||
throw new IllegalArgumentException("cookieMaxAge cannot be greater than " +
|
||||
"rememberMeCookieMaxAge");
|
||||
}
|
||||
this.cookieMaxAge = cookieMaxAge;
|
||||
}
|
||||
|
||||
@@ -304,12 +300,10 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the request attribute name that indicates remember-me login. Used to write
|
||||
* {@link Cookie} with {@code maxAge} property indicated by
|
||||
* {@link #rememberMeCookieMaxAge}.
|
||||
* Set the request attribute name that indicates remember-me login. If specified, the
|
||||
* cookie will be written as Integer.MAX_VALUE.
|
||||
* @param rememberMeRequestAttribute the remember-me request attribute name
|
||||
* @since 1.3.0
|
||||
* @see #setRememberMeCookieMaxAge(int)
|
||||
*/
|
||||
public void setRememberMeRequestAttribute(String rememberMeRequestAttribute) {
|
||||
if (rememberMeRequestAttribute == null) {
|
||||
@@ -319,20 +313,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
this.rememberMeRequestAttribute = rememberMeRequestAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code maxAge} property of the {@link Cookie} to be used when remember-me
|
||||
* is requested. The default is {@link Integer#MAX_VALUE}.
|
||||
* @param rememberMeCookieMaxAge the {@code maxAge} property of the {@code Cookie}
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public void setRememberMeCookieMaxAge(int rememberMeCookieMaxAge) {
|
||||
if (rememberMeCookieMaxAge < 1 || rememberMeCookieMaxAge < this.cookieMaxAge) {
|
||||
throw new IllegalArgumentException("rememberMeCookieMaxAge must be greater " +
|
||||
"than zero and greater than cookieMaxAge");
|
||||
}
|
||||
this.rememberMeCookieMaxAge = rememberMeCookieMaxAge;
|
||||
}
|
||||
|
||||
private String getDomainName(HttpServletRequest request) {
|
||||
if (this.domainName != null) {
|
||||
return this.domainName;
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.security.SpringSessionRememberMeServices;
|
||||
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
|
||||
import org.springframework.session.web.http.CookieHttpSessionStrategy;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
import org.springframework.session.web.http.SessionEventHttpSessionListenerAdapter;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.security;
|
||||
package org.springframework.session.security.web.authentication;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -50,44 +50,48 @@ public class SpringSessionRememberMeServicesTests {
|
||||
@Test
|
||||
public void create() {
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "parameter"))
|
||||
.isEqualTo("remember-me");
|
||||
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember"))
|
||||
.isEqualTo(false);
|
||||
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds"))
|
||||
.isEqualTo(2592000);
|
||||
assertThat(ReflectionTestUtils.getField(this.rememberMeServices,
|
||||
"rememberMeParameterName")).isEqualTo("remember-me");
|
||||
assertThat(
|
||||
ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember"))
|
||||
.isEqualTo(false);
|
||||
assertThat(
|
||||
ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds"))
|
||||
.isEqualTo(2592000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithCustomParameter() {
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.setParameter("test-param");
|
||||
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "parameter"))
|
||||
.isEqualTo("test-param");
|
||||
this.rememberMeServices.setRememberMeParameterName("test-param");
|
||||
assertThat(ReflectionTestUtils.getField(this.rememberMeServices,
|
||||
"rememberMeParameterName")).isEqualTo("test-param");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithNullParameter() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Parameter name cannot be empty or null");
|
||||
this.thrown.expectMessage("rememberMeParameterName cannot be empty or null");
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.setParameter(null);
|
||||
this.rememberMeServices.setRememberMeParameterName(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithAlwaysRemember() {
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.setAlwaysRemember(true);
|
||||
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember"))
|
||||
.isEqualTo(true);
|
||||
assertThat(
|
||||
ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember"))
|
||||
.isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithCustomValidity() {
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.setValiditySeconds(100000);
|
||||
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds"))
|
||||
.isEqualTo(100000);
|
||||
assertThat(
|
||||
ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds"))
|
||||
.isEqualTo(100000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -139,7 +143,7 @@ public class SpringSessionRememberMeServicesTests {
|
||||
given(request.getParameter(eq("test-param"))).willReturn("true");
|
||||
given(request.getSession()).willReturn(session);
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.setParameter("test-param");
|
||||
this.rememberMeServices.setRememberMeParameterName("test-param");
|
||||
this.rememberMeServices.loginSuccess(request, response, authentication);
|
||||
verify(request, times(1)).getParameter(eq("test-param"));
|
||||
verify(request, times(1)).getSession();
|
||||
@@ -172,8 +176,7 @@ public class SpringSessionRememberMeServicesTests {
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
Authentication authentication = mock(Authentication.class);
|
||||
HttpSession session = mock(HttpSession.class);
|
||||
given(request.getParameter(eq("remember-me")))
|
||||
.willReturn("true");
|
||||
given(request.getParameter(eq("remember-me"))).willReturn("true");
|
||||
given(request.getSession()).willReturn(session);
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.setValiditySeconds(100000);
|
||||
@@ -431,23 +431,6 @@ public class DefaultCookieSerializerTests {
|
||||
|
||||
// --- rememberMe ---
|
||||
|
||||
@Test
|
||||
public void setRememberMeCookieMaxAgeNotGreaterThanZero() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("rememberMeCookieMaxAge must be greater than zero and " +
|
||||
"greater than cookieMaxAge");
|
||||
this.serializer.setRememberMeCookieMaxAge(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setRememberMeCookieMaxAgeNotGreaterMaxCookieAge() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("rememberMeCookieMaxAge must be greater than zero and " +
|
||||
"greater than cookieMaxAge");
|
||||
this.serializer.setCookieMaxAge(20);
|
||||
this.serializer.setRememberMeCookieMaxAge(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeCookieRememberMeCookieMaxAgeDefault() {
|
||||
this.request.setAttribute("rememberMe", true);
|
||||
@@ -457,17 +440,6 @@ public class DefaultCookieSerializerTests {
|
||||
assertThat(getCookie().getMaxAge()).isEqualTo(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeCookieRememberMeCookieMaxAgeExplicit() {
|
||||
this.request.setAttribute("rememberMe", true);
|
||||
this.serializer.setRememberMeRequestAttribute("rememberMe");
|
||||
this.serializer.setRememberMeCookieMaxAge(100);
|
||||
|
||||
this.serializer.writeCookieValue(cookieValue(this.sessionId));
|
||||
|
||||
assertThat(getCookie().getMaxAge()).isEqualTo(100);
|
||||
}
|
||||
|
||||
public void setCookieName(String cookieName) {
|
||||
this.cookieName = cookieName;
|
||||
this.serializer.setCookieName(cookieName);
|
||||
|
||||
Reference in New Issue
Block a user