Additional changes related to SEC-192 (avoiding session creation when creating WebAuthenticationDetails). Also fixed Jalopy chaos in SwitchUserProcessingFilter.

This commit is contained in:
Luke Taylor 2006-02-20 00:37:39 +00:00
parent 52a212e609
commit 6abceb7ab0
6 changed files with 347 additions and 370 deletions

View File

@ -102,9 +102,10 @@ public class CasProcessingFilter extends AbstractProcessingFilter {
password = "";
}
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
password);
authRequest.setDetails(new WebAuthenticationDetails(request));
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(username, password);
authRequest.setDetails(new WebAuthenticationDetails(request, false));
return this.getAuthenticationManager().authenticate(authRequest);
}

View File

@ -369,9 +369,10 @@ public class DigestProcessingFilter implements Filter, InitializingBean,
+ "' with response: '" + responseDigest + "'");
}
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user,
user.getPassword());
authRequest.setDetails(new WebAuthenticationDetails(httpRequest));
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(user, user.getPassword());
authRequest.setDetails(new WebAuthenticationDetails(httpRequest, false));
SecurityContextHolder.getContext().setAuthentication(authRequest);
}

View File

@ -104,6 +104,10 @@ import org.springframework.util.Assert;
* </pre>
* </p>
*
*
* @author Mark St.Godard
* @version $Id$
*
* @see org.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority
*/
public class SwitchUserProcessingFilter implements Filter, InitializingBean,
@ -156,10 +160,10 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean,
Authentication current = SecurityContextHolder.getContext()
.getAuthentication();
if (null == current) {
throw new AuthenticationCredentialsNotFoundException(messages
.getMessage("SwitchUserProcessingFilter.noCurrentUser",
"No current user associated with this request"));
if (null == current) {
throw new AuthenticationCredentialsNotFoundException(messages
.getMessage("SwitchUserProcessingFilter.noCurrentUser",
"No current user associated with this request"));
}
// check to see if the current user did actual switch to another user
@ -173,381 +177,352 @@ public class SwitchUserProcessingFilter implements Filter, InitializingBean,
.getMessage(
"SwitchUserProcessingFilter.noOriginalAuthentication",
"Could not find original Authentication object"));
}
// get the source user details
UserDetails originalUser = null;
Object obj = original.getPrincipal();
if ((obj != null) && obj instanceof UserDetails) {
originalUser = (UserDetails) obj;
}
// publish event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(
current, originalUser));
}
return original;
}
/**
* Attempt to switch to another user. If the user does not exist or
* is not active, return null.
*
* @param request The http request
*
* @return The new <code>Authentication</code> request if
* successfully switched to another user,
* <code>null</code> otherwise.
*
* @throws AuthenticationException
* @throws UsernameNotFoundException If the target user is not
* found.
* @throws LockedException DOCUMENT ME!
* @throws DisabledException If the target user is disabled.
* @throws AccountExpiredException If the target user account is
* expired.
* @throws CredentialsExpiredException If the target user
* credentials are expired.
*/
protected Authentication attemptSwitchUser(
// get the source user details
UserDetails originalUser = null;
Object obj = original.getPrincipal();
if ((obj != null) && obj instanceof UserDetails) {
originalUser = (UserDetails) obj;
}
// publish event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(
current, originalUser));
}
return original;
}
/**
* Attempt to switch to another user. If the user does not exist or
* is not active, return null.
*
* @param request The http request
*
* @return The new <code>Authentication</code> request if
* successfully switched to another user,
* <code>null</code> otherwise.
*
* @throws AuthenticationException
* @throws UsernameNotFoundException If the target user is not
* found.
* @throws LockedException DOCUMENT ME!
* @throws DisabledException If the target user is disabled.
* @throws AccountExpiredException If the target user account is
* expired.
* @throws CredentialsExpiredException If the target user
* credentials are expired.
*/
protected Authentication attemptSwitchUser(
HttpServletRequest request) throws AuthenticationException {
UsernamePasswordAuthenticationToken targetUserRequest = null;
UsernamePasswordAuthenticationToken targetUserRequest = null;
String username = request.getParameter(ACEGI_SECURITY_SWITCH_USERNAME_KEY);
String username = request.getParameter(ACEGI_SECURITY_SWITCH_USERNAME_KEY);
if (username == null) {
username = "";
if (username == null) {
username = "";
}
if (logger.isDebugEnabled()) {
logger.debug("Attempt to switch to user [" + username + "]");
}
// load the user by name
UserDetails targetUser = this.userDetailsService
.loadUserByUsername(username);
// user not found
if (targetUser == null) {
throw new UsernameNotFoundException(messages.getMessage(
"SwitchUserProcessingFilter.usernameNotFound",
new Object[] {username},
"Username {0} not found"));
}
// account is expired
if (!targetUser.isAccountNonLocked()) {
throw new LockedException(messages.getMessage(
"SwitchUserProcessingFilter.locked",
"User account is locked"));
}
// user is disabled
if (!targetUser.isEnabled()) {
throw new DisabledException(messages.getMessage(
"SwitchUserProcessingFilter.disabled",
"User is disabled"));
}
// account is expired
if (!targetUser.isAccountNonExpired()) {
throw new AccountExpiredException(messages.getMessage(
"SwitchUserProcessingFilter.expired",
"User account has expired"));
}
// credentials expired
if (!targetUser.isCredentialsNonExpired()) {
throw new CredentialsExpiredException(messages
.getMessage(
"SwitchUserProcessingFilter.credentialsExpired",
"User credentials have expired"));
}
// ok, create the switch user token
targetUserRequest = createSwitchUserToken(request,
username, targetUser);
if (logger.isDebugEnabled()) {
logger.debug("Switch User Token [" + targetUserRequest + "]");
}
// publish event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(
SecurityContextHolder.getContext().getAuthentication(),
targetUser));
}
return targetUserRequest;
}
/**
* Create a switch user token that contains an additional
* <tt>GrantedAuthority</tt> that contains the original
* <code>Authentication</code> object.
*
* @param request The http servlet request.
* @param username The username of target user
* @param targetUser The target user
*
* @return The authentication token
*
* @see SwitchUserGrantedAuthority
*/
private UsernamePasswordAuthenticationToken createSwitchUserToken(
HttpServletRequest request, String username,
UserDetails targetUser) {
UsernamePasswordAuthenticationToken targetUserRequest;
// grant an additional authority that contains the original Authentication object
// which will be used to 'exit' from the current switched user.
Authentication currentAuth = SecurityContextHolder.getContext()
.getAuthentication();
GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(ROLE_PREVIOUS_ADMINISTRATOR,
currentAuth);
// get the original authorities
List orig = Arrays.asList(targetUser.getAuthorities());
// add the new switch user authority
List newAuths = new ArrayList(orig);
newAuths.add(switchAuthority);
GrantedAuthority[] authorities = {};
authorities = (GrantedAuthority[]) newAuths.toArray(authorities);
// create the new authentication token
targetUserRequest = new UsernamePasswordAuthenticationToken(targetUser,
targetUser.getPassword(), authorities);
// set details
targetUserRequest.setDetails(new WebAuthenticationDetails(
request, false));
return targetUserRequest;
}
public void destroy() {}
/**
* @see javax.servlet.Filter#doFilter
*/
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Assert.isInstanceOf(HttpServletRequest.class, request);
Assert.isInstanceOf(HttpServletResponse.class, response);
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// check for switch or exit request
if (requiresSwitchUser(httpRequest)) {
// if set, attempt switch and store original
Authentication targetUser = attemptSwitchUser(httpRequest);
// update the current context to the new target user
SecurityContextHolder.getContext()
.setAuthentication(targetUser);
// redirect to target url
httpResponse.sendRedirect(httpResponse
.encodeRedirectURL(httpRequest
.getContextPath() + targetUrl));
return;
} else if (requiresExitUser(httpRequest)) {
// get the original authentication object (if exists)
Authentication originalUser = attemptExitUser(httpRequest);
// update the current context back to the original user
SecurityContextHolder.getContext()
.setAuthentication(originalUser);
// redirect to target url
httpResponse.sendRedirect(httpResponse.encodeRedirectURL(
httpRequest.getContextPath() + targetUrl));
return;
}
chain.doFilter(request, response);
}
/**
* Find the original <code>Authentication</code> object from
* the current user's granted authorities. A successfully switched
* user should have a <code>SwitchUserGrantedAuthority</code>
* that contains the original source user <code>Authentication</code>
* object.
*
* @param current The current <code>Authentication</code>
* object
*
* @return The source user <code>Authentication</code>
* object or <code>null</code> otherwise.
*/
private Authentication getSourceAuthentication(
Authentication current) {
Authentication original = null;
// iterate over granted authorities and find the 'switch user' authority
GrantedAuthority[] authorities = current
.getAuthorities();
for (int i = 0; i < authorities.length; i++) {
// check for switch user type of authority
if (authorities[i] instanceof SwitchUserGrantedAuthority) {
original = ((SwitchUserGrantedAuthority) authorities[i])
.getSource();
logger.debug(
"Found original switch user granted authority ["
+ original + "]");
}
}
if (logger.isDebugEnabled()) {
logger.debug("Attempt to switch to user [" + username + "]");
}
return original;
}
// load the user by name
UserDetails targetUser = this.userDetailsService
.loadUserByUsername(username);
public void init(FilterConfig ignored)
throws ServletException {}
// user not found
if (targetUser == null) {
throw new UsernameNotFoundException(messages.getMessage(
"SwitchUserProcessingFilter.usernameNotFound",
new Object[] {username},
"Username {0} not found"));
}
/**
* Checks the request URI for the presence
* of <tt>exitUserUrl</tt>.
*
* @param request The http servlet request
*
* @return <code>true</code> if the request requires a exit user,
* <code>false</code> otherwise.
*
* @see SwitchUserProcessingFilter#exitUserUrl
*/
protected boolean requiresExitUser(
HttpServletRequest request) {
String uri = stripUri(request);
// account is expired
if (!targetUser.isAccountNonLocked()) {
throw new LockedException(messages.getMessage(
"SwitchUserProcessingFilter.locked",
"User account is locked"));
}
return uri.endsWith(request
.getContextPath() + exitUserUrl);
}
// user is disabled
if (!targetUser.isEnabled()) {
throw new DisabledException(messages.getMessage(
"SwitchUserProcessingFilter.disabled",
"User is disabled"));
}
/**
* Checks the request URI for the presence of <tt>switchUserUrl</tt>.
*
* @param request The http servlet request
*
* @return <code>true</code> if the request requires a switch,
* <code>false</code> otherwise.
*
* @see SwitchUserProcessingFilter#switchUserUrl
*/
protected boolean requiresSwitchUser(
HttpServletRequest request) {
String uri = stripUri(request);
// account is expired
if (!targetUser.isAccountNonExpired()) {
throw new AccountExpiredException(messages.getMessage(
"SwitchUserProcessingFilter.expired",
"User account has expired"));
}
return uri.endsWith(request.getContextPath() + switchUserUrl);
}
// credentials expired
if (!targetUser.isCredentialsNonExpired()) {
throw new CredentialsExpiredException(messages
.getMessage(
"SwitchUserProcessingFilter.credentialsExpired",
"User credentials have expired"));
}
public void setApplicationEventPublisher(
ApplicationEventPublisher eventPublisher)
throws BeansException {
this.eventPublisher = eventPublisher;
}
// ok, create the switch user token
targetUserRequest = createSwitchUserToken(request,
username, targetUser);
/**
* Sets the authentication data access object.
*
* @param authenticationDao The authentication dao
*/
public void setUserDetailsService(
UserDetailsService authenticationDao) {
this.userDetailsService = authenticationDao;
}
if (logger.isDebugEnabled()) {
logger.debug("Switch User Token ["
+ targetUserRequest + "]");
}
/**
* Set the URL to respond to exit user processing.
*
* @param exitUserUrl The exit user URL.
*/
public void setExitUserUrl(
String exitUserUrl) {
this.exitUserUrl = exitUserUrl;
}
// publish event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(
SecurityContextHolder.getContext()
.getAuthentication(),
targetUser));
}
public void setMessageSource(
MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
return targetUserRequest;
}
/**
* Set the URL to respond to switch user processing.
*
* @param switchUserUrl The switch user URL.
*/
public void setSwitchUserUrl(String switchUserUrl) {
this.switchUserUrl = switchUserUrl;
}
/**
* Create a switch user token that contains an additional
* <tt>GrantedAuthority</tt> that contains the original
* <code>Authentication</code> object.
*
* @param request The http servlet request.
* @param username The username of target user
* @param targetUser The target user
*
* @return The authentication token
*
* @see SwitchUserGrantedAuthority
*/
private UsernamePasswordAuthenticationToken createSwitchUserToken(
HttpServletRequest request, String username,
UserDetails targetUser) {
UsernamePasswordAuthenticationToken targetUserRequest;
/**
* Sets the URL to go to after a successful switch / exit user
* request.
*
* @param targetUrl The target url.
*/
public void setTargetUrl(
String targetUrl) {
this.targetUrl = targetUrl;
}
// grant an additional authority that contains the original Authentication object
// which will be used to 'exit' from the current switched user.
Authentication currentAuth = SecurityContextHolder.getContext()
.getAuthentication();
GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(ROLE_PREVIOUS_ADMINISTRATOR,
currentAuth);
/**
* Strips any content after the ';' in the request URI
*
* @param request The http request
*
* @return The stripped uri
*/
private static String stripUri(HttpServletRequest request) {
String uri = request.getRequestURI();
int idx = uri.indexOf(';');
// get the original authorities
List orig = Arrays.asList(targetUser.getAuthorities());
if (idx > 0) {
uri = uri.substring(0,
idx);
}
// add the new switch user authority
List newAuths = new ArrayList(orig);
newAuths.add(switchAuthority);
GrantedAuthority[] authorities = {};
authorities = (GrantedAuthority[]) newAuths.toArray(authorities);
// create the new authentication token
targetUserRequest = new UsernamePasswordAuthenticationToken(targetUser,
targetUser.getPassword(), authorities);
// set details
targetUserRequest.setDetails(new WebAuthenticationDetails(
request));
return targetUserRequest;
}
public void destroy() {}
/**
* @see javax.servlet.Filter#doFilter
*/
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Assert.isInstanceOf(HttpServletRequest.class, request);
Assert.isInstanceOf(HttpServletResponse.class, response);
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// check for switch or exit request
if (requiresSwitchUser(httpRequest)) {
// if set, attempt switch and store original
Authentication targetUser = attemptSwitchUser(httpRequest);
// update the current context to the new target user
SecurityContextHolder.getContext()
.setAuthentication(targetUser);
// redirect to target url
httpResponse.sendRedirect(httpResponse
.encodeRedirectURL(httpRequest
.getContextPath() + targetUrl));
return;
} else if (requiresExitUser(httpRequest)) {
// get the original authentication object (if exists)
Authentication originalUser = attemptExitUser(httpRequest);
// update the current context back to the original user
SecurityContextHolder.getContext()
.setAuthentication(originalUser);
// redirect to target url
httpResponse.sendRedirect(httpResponse
.encodeRedirectURL(httpRequest
.getContextPath()
+ targetUrl));
return;
}
chain.doFilter(request, response);
}
/**
* Find the original
* <code>Authentication</code> object from
* the current user's granted authorities.
* A successfully switched user should
* have a
* <code>SwitchUserGrantedAuthority</code>
* that contains the original source user
* <code>Authentication</code> object.
*
* @param current The current
* <code>Authentication</code>
* object
*
* @return The source user
* <code>Authentication</code>
* object or <code>null</code>
* otherwise.
*/
private Authentication getSourceAuthentication(
Authentication current) {
Authentication original = null;
// iterate over granted authorities and find the 'switch user' authority
GrantedAuthority[] authorities = current
.getAuthorities();
for (int i = 0; i < authorities.length;
i++) {
// check for switch user type of authority
if (authorities[i] instanceof SwitchUserGrantedAuthority) {
original = ((SwitchUserGrantedAuthority) authorities[i])
.getSource();
logger.debug(
"Found original switch user granted authority ["
+ original + "]");
}
}
return original;
}
public void init(FilterConfig ignored)
throws ServletException {}
/**
* Checks the request URI for the presence
* of <tt>exitUserUrl</tt>.
*
* @param request The http servlet request
*
* @return <code>true</code> if the request
* requires a exit user,
* <code>false</code> otherwise.
*
* @see SwitchUserProcessingFilter#exitUserUrl
*/
protected boolean requiresExitUser(
HttpServletRequest request) {
String uri = stripUri(request);
return uri.endsWith(request
.getContextPath() + exitUserUrl);
}
/**
* Checks the request URI for the
* presence of <tt>switchUserUrl</tt>.
*
* @param request The http servlet
* request
*
* @return <code>true</code> if the
* request requires a switch,
* <code>false</code>
* otherwise.
*
* @see SwitchUserProcessingFilter#switchUserUrl
*/
protected boolean requiresSwitchUser(
HttpServletRequest request) {
String uri = stripUri(request);
return uri.endsWith(request
.getContextPath()
+ switchUserUrl);
}
public void setApplicationEventPublisher(
ApplicationEventPublisher eventPublisher)
throws BeansException {
this.eventPublisher = eventPublisher;
}
/**
* Sets the authentication data
* access object.
*
* @param authenticationDao The
* authentication dao
*/
public void setUserDetailsService(
UserDetailsService authenticationDao) {
this.userDetailsService = authenticationDao;
}
/**
* Set the URL to respond to exit
* user processing.
*
* @param exitUserUrl The exit user
* URL.
*/
public void setExitUserUrl(
String exitUserUrl) {
this.exitUserUrl = exitUserUrl;
}
public void setMessageSource(
MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
/**
* Set the URL to respond to switch
* user processing.
*
* @param switchUserUrl The switch
* user URL.
*/
public void setSwitchUserUrl(
String switchUserUrl) {
this.switchUserUrl = switchUserUrl;
}
/**
* Sets the URL to go to after a
* successful switch / exit user
* request.
*
* @param targetUrl The target url.
*/
public void setTargetUrl(
String targetUrl) {
this.targetUrl = targetUrl;
}
/**
* Strips any content after the ';'
* in the request URI
*
* @param request The http request
*
* @return The stripped uri
*/
private static String stripUri(
HttpServletRequest request) {
String uri = request
.getRequestURI();
int idx = uri.indexOf(';');
if (idx > 0) {
uri = uri.substring(0,
idx);
}
return uri;
}
}
return uri;
}
}

View File

@ -103,7 +103,7 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter {
*/
protected void setDetails(HttpServletRequest request,
UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(new WebAuthenticationDetails(request));
authRequest.setDetails(new WebAuthenticationDetails(request, false));
}
/**

View File

@ -240,7 +240,7 @@ public class SiteminderAuthenticationProcessingFilter
*/
protected void setDetails(HttpServletRequest request,
UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(new WebAuthenticationDetails(request));
authRequest.setDetails(new WebAuthenticationDetails(request, false));
}
/**

View File

@ -118,6 +118,6 @@ public class ConcurrentSessionControllerImplTests extends TestCase {
request.setSession(session);
request.setUserPrincipal(auth);
return new WebAuthenticationDetails(request);
return new WebAuthenticationDetails(request, false);
}
}