package security.filter; import java.io.IOException; import java.lang.reflect.Method; 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.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.context.SecurityContextImpl; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import security.SecUser; public class HttpSessionContextIntegrationFilter implements Filter { private static final Logger logger=LoggerFactory.getLogger(HttpSessionContextIntegrationFilter.class); private boolean forceEagerSessionCreation = false; private boolean cloneFromHttpSession = false; public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; private Class contextClass = SecurityContextImpl.class; @Override public void destroy() { // TODO Auto-generated method stub } private static final String FILTER_APPLIED = "_security_userContextFilter_filterApplied"; private boolean observeOncePerRequest = true; @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpSession httpSession = safeGetSession(request, forceEagerSessionCreation); SecurityContext contextBeforeChainExecution = readSecurityContextFromSession(httpSession); httpSession = null; if (contextBeforeChainExecution == null) { contextBeforeChainExecution = generateNewContext(); if (logger.isDebugEnabled()) { logger.debug("New SecurityContext instance will be associated with SecurityContextHolder"); } } else { if (logger.isDebugEnabled()) { logger.debug("Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT to " + "associate with SecurityContextHolder: '" + contextBeforeChainExecution + "'"); } } try { // This is the only place in this class where // SecurityContextHolder.setContext() is called SecurityContextHolder.setContext(contextBeforeChainExecution); if ((request != null) && (request.getAttribute(FILTER_APPLIED) == null) && observeOncePerRequest) { if (request != null) { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); } Object principal = security.SecurityAppUserHolder.getCurrentUser(); if (principal instanceof SecUser) { // 把用户放入request request.setAttribute("_currentUser", principal); } } chain.doFilter(request, res); } finally { // Crucial removal of SecurityContextHolder contents - do this // before anything else. SecurityContextHolder.clearContext(); } } public SecurityContext generateNewContext() throws ServletException { try { return (SecurityContext) this.contextClass.newInstance(); } catch (InstantiationException ie) { throw new ServletException(ie); } catch (IllegalAccessException iae) { throw new ServletException(iae); } } private SecurityContext readSecurityContextFromSession( HttpSession httpSession) { if (httpSession == null) { if (logger.isDebugEnabled()) { logger.debug("No HttpSession currently exists"); } return null; } // Session exists, so try to obtain a context from it. Object contextFromSessionObject = httpSession .getAttribute(SPRING_SECURITY_CONTEXT_KEY); if (contextFromSessionObject == null) { if (logger.isDebugEnabled()) { logger.debug("HttpSession returned null object for SPRING_SECURITY_CONTEXT"); } return null; } // We now have the security context object from the session. // Clone if required (see SEC-356) if (cloneFromHttpSession) { Assert.isInstanceOf(Cloneable.class, contextFromSessionObject, "Context must implement Clonable and provide a Object.clone() method"); try { Method m = contextFromSessionObject.getClass().getMethod( "clone", new Class[] {}); if (!m.isAccessible()) { m.setAccessible(true); } contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[] {}); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } if (!(contextFromSessionObject instanceof SecurityContext)) { logger.warn("SPRING_SECURITY_CONTEXT did not contain a SecurityContext but contained: '" + contextFromSessionObject + "'; are you improperly modifying the HttpSession directly " + "(you should always use SecurityContextHolder) or using the HttpSession attribute " + "reserved for this class?"); return null; } // Everything OK. The only non-null return from this method. return (SecurityContext) contextFromSessionObject; } private HttpSession safeGetSession(HttpServletRequest request, boolean allowCreate) { try { return request.getSession(allowCreate); } catch (IllegalStateException ignored) { return null; } } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }