SEC-1430: Removed caching of username in session upon failed authentication. Improved Javadoc.
This commit is contained in:
parent
d64efe9747
commit
43be9ea2a4
|
@ -123,8 +123,6 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing
|
||||||
|
|
||||||
if (!StringUtils.hasText(identity)) {
|
if (!StringUtils.hasText(identity)) {
|
||||||
String claimedIdentity = obtainUsername(request);
|
String claimedIdentity = obtainUsername(request);
|
||||||
// Make the username available to the view
|
|
||||||
setLastUsername(claimedIdentity, request);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String returnToUrl = buildReturnToUrl(request);
|
String returnToUrl = buildReturnToUrl(request);
|
||||||
|
@ -159,21 +157,9 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing
|
||||||
// delegate to the authentication provider
|
// delegate to the authentication provider
|
||||||
Authentication authentication = this.getAuthenticationManager().authenticate(token);
|
Authentication authentication = this.getAuthenticationManager().authenticate(token);
|
||||||
|
|
||||||
if (authentication.isAuthenticated()) {
|
|
||||||
setLastUsername(token.getIdentityUrl(), request);
|
|
||||||
}
|
|
||||||
|
|
||||||
return authentication;
|
return authentication;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLastUsername(String username, HttpServletRequest request) {
|
|
||||||
HttpSession session = request.getSession(false);
|
|
||||||
|
|
||||||
if (session != null || getAllowSessionCreation()) {
|
|
||||||
request.getSession().setAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY, username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String lookupRealm(String returnToUrl) {
|
protected String lookupRealm(String returnToUrl) {
|
||||||
String mapping = realmMapping.get(returnToUrl);
|
String mapping = realmMapping.get(returnToUrl);
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
<form name="f" action="<c:url value='j_spring_security_check'/>" method="POST">
|
<form name="f" action="<c:url value='j_spring_security_check'/>" method="POST">
|
||||||
<table>
|
<table>
|
||||||
<tr><td>User:</td><td><input type='text' name='j_username' <% if (session.getAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY) != null) { %>value='<%= session.getAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY) %>'<% } %>></td></tr>
|
<tr><td>User:</td><td><input type='text' name='j_username' /></td></tr>
|
||||||
<tr><td>Password:</td><td><input type='password' name='j_password'></td></tr>
|
<tr><td>Password:</td><td><input type='password' name='j_password'/></td></tr>
|
||||||
<tr><td><input type="checkbox" name="_spring_security_remember_me"></td><td>Don't ask for my password for two weeks</td></tr>
|
<tr><td><input type="checkbox" name="_spring_security_remember_me"></td><td>Don't ask for my password for two weeks</td></tr>
|
||||||
|
|
||||||
<tr><td colspan='2'><input name="submit" type="submit"></td></tr>
|
<tr><td colspan='2'><input name="submit" type="submit"></td></tr>
|
||||||
|
|
|
@ -7,7 +7,18 @@ package org.springframework.security.web;
|
||||||
* @since 3.0.3
|
* @since 3.0.3
|
||||||
*/
|
*/
|
||||||
public final class WebAttributes {
|
public final class WebAttributes {
|
||||||
|
/**
|
||||||
|
* Used to cache an {@code AccessDeniedException} in the request for rendering.
|
||||||
|
*
|
||||||
|
* @see org.springframework.security.web.access.AccessDeniedHandlerImpl
|
||||||
|
*/
|
||||||
public static final String ACCESS_DENIED_403 = "SPRING_SECURITY_403_EXCEPTION";
|
public static final String ACCESS_DENIED_403 = "SPRING_SECURITY_403_EXCEPTION";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to cache an authentication-failure exception in the session.
|
||||||
|
*
|
||||||
|
* @see org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
|
||||||
|
*/
|
||||||
public static final String AUTHENTICATION_EXCEPTION = "SPRING_SECURITY_LAST_EXCEPTION";
|
public static final String AUTHENTICATION_EXCEPTION = "SPRING_SECURITY_LAST_EXCEPTION";
|
||||||
public static final String LAST_USERNAME = "SPRING_SECURITY_LAST_USERNAME";
|
public static final String LAST_USERNAME = "SPRING_SECURITY_LAST_USERNAME";
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,5 @@ public class SimpleUrlAuthenticationSuccessHandler extends AbstractAuthenticatio
|
||||||
}
|
}
|
||||||
|
|
||||||
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||||
session.removeAttribute(WebAttributes.LAST_USERNAME);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,10 @@ public class UsernamePasswordAuthenticationFilter extends AbstractAuthentication
|
||||||
|
|
||||||
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
|
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
|
||||||
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
|
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
|
||||||
|
/**
|
||||||
|
* @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
|
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
|
||||||
|
|
||||||
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
|
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
|
||||||
|
@ -84,13 +88,6 @@ public class UsernamePasswordAuthenticationFilter extends AbstractAuthentication
|
||||||
|
|
||||||
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
|
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
|
||||||
|
|
||||||
// Place the last username attempted into HttpSession for views
|
|
||||||
HttpSession session = request.getSession(false);
|
|
||||||
|
|
||||||
if (session != null || getAllowSessionCreation()) {
|
|
||||||
request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextEscapeUtils.escapeEntities(username));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow subclasses to set the "details" property
|
// Allow subclasses to set the "details" property
|
||||||
setDetails(request, authRequest);
|
setDetails(request, authRequest);
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,9 @@ import java.util.*;
|
||||||
* The default implementation of {@link SessionAuthenticationStrategy}.
|
* The default implementation of {@link SessionAuthenticationStrategy}.
|
||||||
* <p>
|
* <p>
|
||||||
* Creates a new session for the newly authenticated user if they already have a session (as a defence against
|
* Creates a new session for the newly authenticated user if they already have a session (as a defence against
|
||||||
* session-fixation protection attacks), and copies their session attributes across to the new session
|
* session-fixation protection attacks), and copies their session attributes across to the new session.
|
||||||
* (can be disabled by setting {@code migrateSessionAttributes} to {@code false}).
|
* The copying of the attributes can be disabled by setting {@code migrateSessionAttributes} to {@code false}
|
||||||
|
* (note that even in this case, internal Spring Security attributes will still be migrated to the new session).
|
||||||
* <p>
|
* <p>
|
||||||
* This approach will only be effective if your servlet container always assigns a new session Id when a session is
|
* This approach will only be effective if your servlet container always assigns a new session Id when a session is
|
||||||
* invalidated and a new session created by calling {@link HttpServletRequest#getSession()}.
|
* invalidated and a new session created by calling {@link HttpServletRequest#getSession()}.
|
||||||
|
|
|
@ -94,18 +94,13 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||||
private String generateLoginPageHtml(HttpServletRequest request) {
|
private String generateLoginPageHtml(HttpServletRequest request) {
|
||||||
boolean loginError = request.getParameter(ERROR_PARAMETER_NAME) != null;
|
boolean loginError = request.getParameter(ERROR_PARAMETER_NAME) != null;
|
||||||
String errorMsg = "none";
|
String errorMsg = "none";
|
||||||
String lastUser = "";
|
|
||||||
|
|
||||||
if (loginError) {
|
if (loginError) {
|
||||||
HttpSession session = request.getSession(false);
|
HttpSession session = request.getSession(false);
|
||||||
|
|
||||||
if(session != null) {
|
if(session != null) {
|
||||||
lastUser = (String) session.getAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY);
|
|
||||||
AuthenticationException ex = (AuthenticationException) session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
AuthenticationException ex = (AuthenticationException) session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||||
errorMsg = ex != null ? ex.getMessage() : "none";
|
errorMsg = ex != null ? ex.getMessage() : "none";
|
||||||
if (lastUser == null) {
|
|
||||||
lastUser = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +123,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
||||||
sb.append("<form name='f' action='").append(request.getContextPath()).append(authenticationUrl).append("' method='POST'>\n");
|
sb.append("<form name='f' action='").append(request.getContextPath()).append(authenticationUrl).append("' method='POST'>\n");
|
||||||
sb.append(" <table>\n");
|
sb.append(" <table>\n");
|
||||||
sb.append(" <tr><td>User:</td><td><input type='text' name='");
|
sb.append(" <tr><td>User:</td><td><input type='text' name='");
|
||||||
sb.append(usernameParameter).append("' value='").append(lastUser).append("'></td></tr>\n");
|
sb.append(usernameParameter).append("' value='").append("'></td></tr>\n");
|
||||||
sb.append(" <tr><td>Password:</td><td><input type='password' name='").append(passwordParameter).append("'/></td></tr>\n");
|
sb.append(" <tr><td>Password:</td><td><input type='password' name='").append(passwordParameter).append("'/></td></tr>\n");
|
||||||
|
|
||||||
if (rememberMeParameter != null) {
|
if (rememberMeParameter != null) {
|
||||||
|
|
|
@ -55,8 +55,6 @@ public class UsernamePasswordAuthenticationFilterTests extends TestCase {
|
||||||
|
|
||||||
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
|
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
|
||||||
assertTrue(result != null);
|
assertTrue(result != null);
|
||||||
assertEquals("rod", request.getSession().getAttribute(
|
|
||||||
UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY));
|
|
||||||
assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress());
|
assertEquals("127.0.0.1", ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,10 +121,6 @@ public class UsernamePasswordAuthenticationFilterTests extends TestCase {
|
||||||
fail("Expected AuthenticationException");
|
fail("Expected AuthenticationException");
|
||||||
} catch (AuthenticationException e) {
|
} catch (AuthenticationException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check username has still been set
|
|
||||||
assertEquals("rod", request.getSession().getAttribute(
|
|
||||||
UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue