📄 httpsessioncontextintegrationfilter.java
字号:
* If the session is null, the context object is null or the context object stored in the session * is not an instance of SecurityContext it will return null. * <p/> * If <tt>cloneFromHttpSession</tt> is set to true, it will attempt to clone the context object * and return the cloned instance. * * @param httpSession the session obtained from the request. */ 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(ACEGI_SECURITY_CONTEXT_KEY); if (contextFromSessionObject == null) { if (logger.isDebugEnabled()) { logger.debug("HttpSession returned null object for ACEGI_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)) { if (logger.isWarnEnabled()) { logger.warn("ACEGI_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; } /** * Stores the supplied security context in the session (if available) and if it has changed since it was * set at the start of the request. * * @param securityContext the context object obtained from the SecurityContextHolder after the request has * been processed by the filter chain. SecurityContextHolder.getContext() cannot be used to obtain * the context as it has already been cleared by the time this method is called. * @param request the request object (used to obtain the session, if one exists). * @param httpSessionExistedAtStartOfRequest indicates whether there was a session in place before the * filter chain executed. If this is true, and the session is found to be null, this indicates that it was * invalidated during the request and a new session will now be created. * @param contextHashBeforeChainExecution the hashcode of the context before the filter chain executed. * The context will only be stored if it has a different hashcode, indicating that the context changed * during the request. * */ private void storeSecurityContextInSession(SecurityContext securityContext, HttpServletRequest request, boolean httpSessionExistedAtStartOfRequest, int contextHashBeforeChainExecution) { HttpSession httpSession = null; try { httpSession = request.getSession(false); } catch (IllegalStateException ignored) { } if (httpSession == null) { if (httpSessionExistedAtStartOfRequest) { if (logger.isDebugEnabled()) { logger.debug("HttpSession is now null, but was not null at start of request; " + "session was invalidated, so do not create a new session"); } } else { // Generate a HttpSession only if we need to if (!allowSessionCreation) { if (logger.isDebugEnabled()) { logger.debug("The HttpSession is currently null, and the " + "HttpSessionContextIntegrationFilter is prohibited from creating an HttpSession " + "(because the allowSessionCreation property is false) - SecurityContext thus not " + "stored for next request"); } } else if (!contextObject.equals(securityContext)) { if (logger.isDebugEnabled()) { logger.debug("HttpSession being created as SecurityContextHolder contents are non-default"); } try { httpSession = request.getSession(true); } catch (IllegalStateException ignored) { } } else { if (logger.isDebugEnabled()) { logger.debug("HttpSession is null, but SecurityContextHolder has not changed from default: ' " + securityContext + "'; not creating HttpSession or storing SecurityContextHolder contents"); } } } } // If HttpSession exists, store current SecurityContextHolder contents but only if // the SecurityContext has actually changed (see JIRA SEC-37) if (httpSession != null && securityContext.hashCode() != contextHashBeforeChainExecution) { httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY, securityContext); if (logger.isDebugEnabled()) { logger.debug("SecurityContext stored to HttpSession: '" + securityContext + "'"); } } } public SecurityContext generateNewContext() throws ServletException { try { return (SecurityContext) this.context.newInstance(); } catch (InstantiationException ie) { throw new ServletException(ie); } catch (IllegalAccessException iae) { throw new ServletException(iae); } } /** * Does nothing. We use IoC container lifecycle services instead. * * @param filterConfig ignored * @throws ServletException ignored */ public void init(FilterConfig filterConfig) throws ServletException { } /** * Does nothing. We use IoC container lifecycle services instead. */ public void destroy() { } public boolean isAllowSessionCreation() { return allowSessionCreation; } public void setAllowSessionCreation(boolean allowSessionCreation) { this.allowSessionCreation = allowSessionCreation; } public Class getContext() { return context; } public void setContext(Class secureContext) { this.context = secureContext; } public boolean isForceEagerSessionCreation() { return forceEagerSessionCreation; } public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) { this.forceEagerSessionCreation = forceEagerSessionCreation; } //~ Inner Classes ================================================================================================== /** * Wrapper that is applied to every request to update the <code>HttpSession<code> with * the <code>SecurityContext</code> when a <code>sendError()</code> or <code>sendRedirect</code> * happens. See SEC-398. The class contains the fields needed to call * <code>storeSecurityContextInSession()</code> */ private class OnRedirectUpdateSessionResponseWrapper extends HttpServletResponseWrapper { HttpServletRequest request; boolean httpSessionExistedAtStartOfRequest; int contextHashBeforeChainExecution; // Used to ensure storeSecurityContextInSession() is only // called once. boolean sessionUpdateDone = false; /** * Takes the parameters required to call <code>storeSecurityContextInSession()</code> in * addition to the response object we are wrapping. * @see HttpSessionContextIntegrationFilter#storeSecurityContextInSession(SecurityContext, ServletRequest, boolean, int) */ public OnRedirectUpdateSessionResponseWrapper(HttpServletResponse response, HttpServletRequest request, boolean httpSessionExistedAtStartOfRequest, int contextHashBeforeChainExecution) { super(response); this.request = request; this.httpSessionExistedAtStartOfRequest = httpSessionExistedAtStartOfRequest; this.contextHashBeforeChainExecution = contextHashBeforeChainExecution; } /** * Makes sure the session is updated before calling the * superclass <code>sendError()</code> */ public void sendError(int sc) throws IOException { doSessionUpdate(); super.sendError(sc); } /** * Makes sure the session is updated before calling the * superclass <code>sendError()</code> */ public void sendError(int sc, String msg) throws IOException { doSessionUpdate(); super.sendError(sc, msg); } /** * Makes sure the session is updated before calling the * superclass <code>sendRedirect()</code> */ public void sendRedirect(String location) throws IOException { doSessionUpdate(); super.sendRedirect(location); } /** * Calls <code>storeSecurityContextInSession()</code> */ private void doSessionUpdate() { if (sessionUpdateDone) { return; } SecurityContext securityContext = SecurityContextHolder.getContext(); storeSecurityContextInSession(securityContext, request, httpSessionExistedAtStartOfRequest, contextHashBeforeChainExecution); sessionUpdateDone = true; } /** * Tells if the response wrapper has called * <code>storeSecurityContextInSession()</code>. */ public boolean isSessionUpdateDone() { return sessionUpdateDone; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -