mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-31 01:02:14 +00:00
Added event for user context switching and updated switch user filter
This commit is contained in:
parent
55f5c3397a
commit
20ebb668a6
@ -0,0 +1,43 @@
|
|||||||
|
/* Copyright 2004, 2005 Acegi Technology Pty Limited
|
||||||
|
*
|
||||||
|
* 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 net.sf.acegisecurity.providers.dao.event;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.Authentication;
|
||||||
|
import net.sf.acegisecurity.UserDetails;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application event which indicates that a user context switch.
|
||||||
|
*
|
||||||
|
* @author Mark St.Godard
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class AuthenticationSwitchUserEvent extends AuthenticationEvent {
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch user context event constructor
|
||||||
|
*
|
||||||
|
* @param authentication The current <code>Authentication</code> object
|
||||||
|
* @param sourceUser The original user
|
||||||
|
* @param targetUser The target user
|
||||||
|
*/
|
||||||
|
public AuthenticationSwitchUserEvent(Authentication authentication,
|
||||||
|
UserDetails targetUser) {
|
||||||
|
super(authentication, targetUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,29 +15,7 @@
|
|||||||
|
|
||||||
package net.sf.acegisecurity.ui.switchuser;
|
package net.sf.acegisecurity.ui.switchuser;
|
||||||
|
|
||||||
import net.sf.acegisecurity.AccountExpiredException;
|
|
||||||
import net.sf.acegisecurity.Authentication;
|
|
||||||
import net.sf.acegisecurity.AuthenticationCredentialsNotFoundException;
|
|
||||||
import net.sf.acegisecurity.AuthenticationException;
|
|
||||||
import net.sf.acegisecurity.CredentialsExpiredException;
|
|
||||||
import net.sf.acegisecurity.DisabledException;
|
|
||||||
import net.sf.acegisecurity.GrantedAuthority;
|
|
||||||
import net.sf.acegisecurity.UserDetails;
|
|
||||||
import net.sf.acegisecurity.context.SecurityContextHolder;
|
|
||||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
|
||||||
import net.sf.acegisecurity.providers.dao.AuthenticationDao;
|
|
||||||
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
|
|
||||||
import net.sf.acegisecurity.ui.WebAuthenticationDetails;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -51,6 +29,29 @@ import javax.servlet.ServletResponse;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.AccountExpiredException;
|
||||||
|
import net.sf.acegisecurity.Authentication;
|
||||||
|
import net.sf.acegisecurity.AuthenticationCredentialsNotFoundException;
|
||||||
|
import net.sf.acegisecurity.AuthenticationException;
|
||||||
|
import net.sf.acegisecurity.CredentialsExpiredException;
|
||||||
|
import net.sf.acegisecurity.DisabledException;
|
||||||
|
import net.sf.acegisecurity.GrantedAuthority;
|
||||||
|
import net.sf.acegisecurity.UserDetails;
|
||||||
|
import net.sf.acegisecurity.context.SecurityContextHolder;
|
||||||
|
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||||
|
import net.sf.acegisecurity.providers.dao.AuthenticationDao;
|
||||||
|
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
|
||||||
|
import net.sf.acegisecurity.providers.dao.event.AuthenticationSwitchUserEvent;
|
||||||
|
import net.sf.acegisecurity.ui.WebAuthenticationDetails;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch User processing filter responsible for user context switching.
|
* Switch User processing filter responsible for user context switching.
|
||||||
@ -104,7 +105,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
*
|
*
|
||||||
* @see net.sf.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority
|
* @see net.sf.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority
|
||||||
*/
|
*/
|
||||||
public class SwitchUserProcessingFilter implements InitializingBean, Filter {
|
public class SwitchUserProcessingFilter implements Filter, InitializingBean,
|
||||||
|
ApplicationContextAware {
|
||||||
//~ Static fields/initializers =============================================
|
//~ Static fields/initializers =============================================
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(SwitchUserProcessingFilter.class);
|
private static final Log logger = LogFactory.getLog(SwitchUserProcessingFilter.class);
|
||||||
@ -112,19 +114,26 @@ public class SwitchUserProcessingFilter implements InitializingBean, Filter {
|
|||||||
// ~ Static fields/initializers
|
// ~ Static fields/initializers
|
||||||
// =============================================
|
// =============================================
|
||||||
public static final String ACEGI_SECURITY_SWITCH_USERNAME_KEY = "j_username";
|
public static final String ACEGI_SECURITY_SWITCH_USERNAME_KEY = "j_username";
|
||||||
public static final String SWITCH_USER_GRANTED_AUTHORITY = "PREVIOUS_ADMINISTRATOR";
|
public static final String ROLE_PREVIOUS_ADMINISTRATOR = "ROLE_PREVIOUS_ADMINISTRATOR";
|
||||||
|
|
||||||
//~ Instance fields ========================================================
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
private ApplicationContext context;
|
||||||
|
|
||||||
// ~ Instance fields
|
// ~ Instance fields
|
||||||
// ========================================================
|
// ========================================================
|
||||||
private AuthenticationDao authenticationDao;
|
private AuthenticationDao authenticationDao;
|
||||||
private String exitUserUrl;
|
private String exitUserUrl = "/j_acegi_exit_user";
|
||||||
private String switchUserUrl;
|
private String switchUserUrl = "/j_acegi_switch_user";
|
||||||
private String targetUrl;
|
private String targetUrl;
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public void setApplicationContext(ApplicationContext context)
|
||||||
|
throws BeansException {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the authentication data access object.
|
* Sets the authentication data access object.
|
||||||
*
|
*
|
||||||
@ -134,27 +143,6 @@ public class SwitchUserProcessingFilter implements InitializingBean, Filter {
|
|||||||
this.authenticationDao = authenticationDao;
|
this.authenticationDao = authenticationDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This filter by default responds to <code>/j_acegi_exit_user</code>.
|
|
||||||
*
|
|
||||||
* @return the default exit user url
|
|
||||||
*/
|
|
||||||
public String getDefaultExitUserUrl() {
|
|
||||||
return "/j_acegi_exit_user";
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~ Methods
|
|
||||||
// ================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This filter by default responds to <code>/j_acegi_switch_user</code>.
|
|
||||||
*
|
|
||||||
* @return the default switch user url
|
|
||||||
*/
|
|
||||||
public String getDefaultSwitchUserUrl() {
|
|
||||||
return "/j_acegi_switch_user";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the URL to respond to exit user processing.
|
* Set the URL to respond to exit user processing.
|
||||||
*
|
*
|
||||||
@ -196,13 +184,9 @@ public class SwitchUserProcessingFilter implements InitializingBean, Filter {
|
|||||||
*/
|
*/
|
||||||
public void doFilter(ServletRequest request, ServletResponse response,
|
public void doFilter(ServletRequest request, ServletResponse response,
|
||||||
FilterChain chain) throws IOException, ServletException {
|
FilterChain chain) throws IOException, ServletException {
|
||||||
if (!(request instanceof HttpServletRequest)) {
|
|
||||||
throw new ServletException("Can only process HttpServletRequest");
|
Assert.isInstanceOf(HttpServletRequest.class,request);
|
||||||
}
|
Assert.isInstanceOf(HttpServletResponse.class,response);
|
||||||
|
|
||||||
if (!(response instanceof HttpServletResponse)) {
|
|
||||||
throw new ServletException("Can only process HttpServletResponse");
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||||
@ -214,7 +198,7 @@ public class SwitchUserProcessingFilter implements InitializingBean, Filter {
|
|||||||
|
|
||||||
// update the current context to the new target user
|
// update the current context to the new target user
|
||||||
SecurityContextHolder.getContext().setAuthentication(targetUser);
|
SecurityContextHolder.getContext().setAuthentication(targetUser);
|
||||||
|
|
||||||
// redirect to target url
|
// redirect to target url
|
||||||
httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));
|
httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));
|
||||||
|
|
||||||
@ -268,6 +252,12 @@ public class SwitchUserProcessingFilter implements InitializingBean, Filter {
|
|||||||
throw new AuthenticationCredentialsNotFoundException(
|
throw new AuthenticationCredentialsNotFoundException(
|
||||||
"Could not find original Authentication object!");
|
"Could not find original Authentication object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: fix target user on exit
|
||||||
|
if (this.context != null) {
|
||||||
|
context.publishEvent(new AuthenticationSwitchUserEvent(
|
||||||
|
current, null) );
|
||||||
|
}
|
||||||
|
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
@ -333,6 +323,13 @@ public class SwitchUserProcessingFilter implements InitializingBean, Filter {
|
|||||||
logger.debug("Switch User Token [" + targetUserRequest + "]");
|
logger.debug("Switch User Token [" + targetUserRequest + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// publish event
|
||||||
|
if (this.context != null) {
|
||||||
|
context.publishEvent(new AuthenticationSwitchUserEvent(
|
||||||
|
SecurityContextHolder.getContext().getAuthentication(),
|
||||||
|
targetUser) );
|
||||||
|
}
|
||||||
|
|
||||||
return targetUserRequest;
|
return targetUserRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +434,7 @@ public class SwitchUserProcessingFilter implements InitializingBean, Filter {
|
|||||||
// which will be used to 'exit' from the current switched user.
|
// which will be used to 'exit' from the current switched user.
|
||||||
Authentication currentAuth = SecurityContextHolder.getContext()
|
Authentication currentAuth = SecurityContextHolder.getContext()
|
||||||
.getAuthentication();
|
.getAuthentication();
|
||||||
GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(SWITCH_USER_GRANTED_AUTHORITY,
|
GrantedAuthority switchAuthority = new SwitchUserGrantedAuthority(ROLE_PREVIOUS_ADMINISTRATOR,
|
||||||
currentAuth);
|
currentAuth);
|
||||||
|
|
||||||
// get the original authorities
|
// get the original authorities
|
||||||
|
@ -22,6 +22,7 @@ import net.sf.acegisecurity.GrantedAuthority;
|
|||||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||||
import net.sf.acegisecurity.providers.dao.User;
|
import net.sf.acegisecurity.providers.dao.User;
|
||||||
|
import net.sf.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,6 +89,16 @@ public class AuthenticationEventTests extends TestCase {
|
|||||||
assertEquals(user, event.getUser());
|
assertEquals(user, event.getUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSwitchUserContextEvent() {
|
||||||
|
Authentication auth = getAuthentication();
|
||||||
|
User targetUser = getUser();
|
||||||
|
|
||||||
|
AuthenticationSwitchUserEvent event = new AuthenticationSwitchUserEvent(auth,
|
||||||
|
targetUser);
|
||||||
|
assertEquals(auth, event.getAuthentication());
|
||||||
|
assertEquals(targetUser, event.getUser());
|
||||||
|
}
|
||||||
|
|
||||||
private Authentication getAuthentication() {
|
private Authentication getAuthentication() {
|
||||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("Principal",
|
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("Principal",
|
||||||
"Credentials");
|
"Credentials");
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package net.sf.acegisecurity.ui.switchuser;
|
package net.sf.acegisecurity.ui.switchuser;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import net.sf.acegisecurity.AccountExpiredException;
|
import net.sf.acegisecurity.AccountExpiredException;
|
||||||
import net.sf.acegisecurity.Authentication;
|
import net.sf.acegisecurity.Authentication;
|
||||||
import net.sf.acegisecurity.AuthenticationException;
|
import net.sf.acegisecurity.AuthenticationException;
|
||||||
@ -33,7 +32,6 @@ import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
|
|||||||
import net.sf.acegisecurity.util.MockFilterChain;
|
import net.sf.acegisecurity.util.MockFilterChain;
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
|
||||||
@ -191,34 +189,6 @@ public class SwitchUserProcessingFilterTests extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBadConfigMissingExitUserUrl() {
|
|
||||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
|
||||||
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
|
|
||||||
filter.setSwitchUserUrl("/j_acegi_switch_user");
|
|
||||||
filter.setTargetUrl("/main.jsp");
|
|
||||||
|
|
||||||
try {
|
|
||||||
filter.afterPropertiesSet();
|
|
||||||
fail("Expect to fail due to missing 'exitUserUrl'");
|
|
||||||
} catch (Exception expected) {
|
|
||||||
// expected exception
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testBadConfigMissingSwitchUserUrl() {
|
|
||||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
|
||||||
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
|
|
||||||
filter.setExitUserUrl("/j_acegi_exit_user");
|
|
||||||
filter.setTargetUrl("/main.jsp");
|
|
||||||
|
|
||||||
try {
|
|
||||||
filter.afterPropertiesSet();
|
|
||||||
fail("Expect to fail due to missing 'switchUserUrl'");
|
|
||||||
} catch (Exception expected) {
|
|
||||||
// expected exception
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testBadConfigMissingTargetUrl() {
|
public void testBadConfigMissingTargetUrl() {
|
||||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||||
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
|
filter.setAuthenticationDao(new MockAuthenticationDaoUserJackLord());
|
||||||
@ -233,11 +203,6 @@ public class SwitchUserProcessingFilterTests extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDefaultExitProcessUrl() {
|
|
||||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
|
||||||
assertEquals("/j_acegi_exit_user", filter.getDefaultExitUserUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDefaultProcessesFilterUrlWithPathParameter() {
|
public void testDefaultProcessesFilterUrlWithPathParameter() {
|
||||||
MockHttpServletRequest request = createMockSwitchRequest();
|
MockHttpServletRequest request = createMockSwitchRequest();
|
||||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
||||||
@ -248,11 +213,6 @@ public class SwitchUserProcessingFilterTests extends TestCase {
|
|||||||
assertTrue(filter.requiresSwitchUser(request));
|
assertTrue(filter.requiresSwitchUser(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDefaultSwitchProcessUrl() {
|
|
||||||
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
|
|
||||||
assertEquals("/j_acegi_switch_user", filter.getDefaultSwitchUserUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testExitRequestUserJackLordToDano() throws Exception {
|
public void testExitRequestUserJackLordToDano() throws Exception {
|
||||||
// original user
|
// original user
|
||||||
GrantedAuthority[] auths = {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
|
GrantedAuthority[] auths = {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user