📄 switchuserprocessingfilter.java
字号:
/* Copyright 2004, 2005, 2006 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 org.acegisecurity.ui.switchuser;import org.acegisecurity.AccountExpiredException;import org.acegisecurity.AcegiMessageSource;import org.acegisecurity.Authentication;import org.acegisecurity.AuthenticationCredentialsNotFoundException;import org.acegisecurity.AuthenticationException;import org.acegisecurity.CredentialsExpiredException;import org.acegisecurity.DisabledException;import org.acegisecurity.GrantedAuthority;import org.acegisecurity.LockedException;import org.acegisecurity.context.SecurityContextHolder;import org.acegisecurity.event.authentication.AuthenticationSwitchUserEvent;import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;import org.acegisecurity.ui.AuthenticationDetailsSource;import org.acegisecurity.ui.AuthenticationDetailsSourceImpl;import org.acegisecurity.userdetails.UserDetails;import org.acegisecurity.userdetails.UserDetailsService;import org.acegisecurity.userdetails.UsernameNotFoundException;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.ApplicationEventPublisher;import org.springframework.context.ApplicationEventPublisherAware;import org.springframework.context.MessageSource;import org.springframework.context.MessageSourceAware;import org.springframework.context.support.MessageSourceAccessor;import org.springframework.util.Assert;import java.io.IOException;import java.util.ArrayList;import java.util.List;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * Switch User processing filter responsible for user context switching.<p>This filter is similar to Unix 'su' * however for Acegi-managed web applications. A common use-case for this feature is the ability to allow * higher-authority users (i.e. ROLE_ADMIN) to switch to a regular user (i.e. ROLE_USER).</p> * <p>This filter assumes that the user performing the switch will be required to be logged in as normal (i.e. * ROLE_ADMIN user). The user will then access a page/controller that enables the administrator to specify who they * wish to become (see <code>switchUserUrl</code>). <br> * <b>Note: This URL will be required to have to appropriate security contraints configured so that only users of that * role can access (i.e. ROLE_ADMIN).</b></p> * <p>On successful switch, the user's <code>SecurityContextHolder</code> will be updated to reflect the * specified user and will also contain an additinal {@link org.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority * } which contains the original user.</p> * <p>To 'exit' from a user context, the user will then need to access a URL (see <code>exitUserUrl</code>) that * will switch back to the original user as identified by the <code>ROLE_PREVIOUS_ADMINISTRATOR</code>.</p> * <p>To configure the Switch User Processing Filter, create a bean definition for the Switch User processing * filter and add to the filterChainProxy. <br> * Example:<pre> * <bean id="switchUserProcessingFilter" class="org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter"> * <property name="authenticationDao" ref="jdbcDaoImpl" /> * <property name="switchUserUrl"><value>/j_acegi_switch_user</value></property> * <property name="exitUserUrl"><value>/j_acegi_exit_user</value></property> * <property name="targetUrl"><value>/index.jsp</value></property></bean></pre></p> * * @author Mark St.Godard * @version $Id: SwitchUserProcessingFilter.java 2637 2008-02-15 14:35:16Z luke_t $ * * @see org.acegisecurity.ui.switchuser.SwitchUserGrantedAuthority */public class SwitchUserProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(SwitchUserProcessingFilter.class); public static final String ACEGI_SECURITY_SWITCH_USERNAME_KEY = "j_username"; public static final String ROLE_PREVIOUS_ADMINISTRATOR = "ROLE_PREVIOUS_ADMINISTRATOR"; //~ Instance fields ================================================================================================ private ApplicationEventPublisher eventPublisher; private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private String exitUserUrl = "/j_acegi_exit_user"; private String switchUserUrl = "/j_acegi_switch_user"; private String targetUrl; private SwitchUserAuthorityChanger switchUserAuthorityChanger; private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.hasLength(switchUserUrl, "switchUserUrl must be specified"); Assert.hasLength(exitUserUrl, "exitUserUrl must be specified"); Assert.hasLength(targetUrl, "targetUrl must be specified"); Assert.notNull(userDetailsService, "authenticationDao must be specified"); Assert.notNull(messages, "A message source must be set"); } /** * Attempt to exit from an already switched user. * * @param request The http servlet request * * @return The original <code>Authentication</code> object or <code>null</code> otherwise. * * @throws AuthenticationCredentialsNotFoundException If no <code>Authentication</code> associated with this * request. */ protected Authentication attemptExitUser(HttpServletRequest request) throws AuthenticationCredentialsNotFoundException { // need to check to see if the current user has a SwitchUserGrantedAuthority Authentication current = SecurityContextHolder.getContext().getAuthentication(); 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 // if so, get the original source user so we can switch back Authentication original = getSourceAuthentication(current); if (original == null) { logger.error("Could not find original user Authentication object!"); throw new AuthenticationCredentialsNotFoundException(messages.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(HttpServletRequest request) throws AuthenticationException { UsernamePasswordAuthenticationToken targetUserRequest = null; String username = request.getParameter(ACEGI_SECURITY_SWITCH_USERNAME_KEY); 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()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -