package com.hwlcn.security.web.servlet; import com.hwlcn.security.SecurityUtils; import com.hwlcn.security.session.Session; import com.hwlcn.security.subject.ExecutionException; import com.hwlcn.security.subject.Subject; import com.hwlcn.security.web.filter.mgt.FilterChainResolver; import com.hwlcn.security.web.mgt.DefaultWebSecurityManager; import com.hwlcn.security.web.mgt.WebSecurityManager; import com.hwlcn.security.web.subject.WebSubject; import com.hwlcn.security.web.subject.WebSubjectBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.Callable; public abstract class AbstractSecurityFilter extends OncePerRequestFilter { private static final Logger log = LoggerFactory.getLogger(AbstractSecurityFilter.class); private static final String STATIC_INIT_PARAM_NAME = "staticSecurityManagerEnabled"; private WebSecurityManager securityManager; private FilterChainResolver filterChainResolver; private boolean staticSecurityManagerEnabled; protected AbstractSecurityFilter() { this.staticSecurityManagerEnabled = false; } public WebSecurityManager getSecurityManager() { return securityManager; } public void setSecurityManager(WebSecurityManager sm) { this.securityManager = sm; } public FilterChainResolver getFilterChainResolver() { return filterChainResolver; } public void setFilterChainResolver(FilterChainResolver filterChainResolver) { this.filterChainResolver = filterChainResolver; } public boolean isStaticSecurityManagerEnabled() { return staticSecurityManagerEnabled; } public void setStaticSecurityManagerEnabled(boolean staticSecurityManagerEnabled) { this.staticSecurityManagerEnabled = staticSecurityManagerEnabled; } protected final void onFilterConfigSet() throws Exception { applyStaticSecurityManagerEnabledConfig(); init(); ensureSecurityManager(); if (isStaticSecurityManagerEnabled()) { SecurityUtils.setSecurityManager(getSecurityManager()); } } private void applyStaticSecurityManagerEnabledConfig() { String value = getInitParam(STATIC_INIT_PARAM_NAME); if (value != null) { Boolean b = Boolean.valueOf(value); if (b != null) { setStaticSecurityManagerEnabled(b); } } } public void init() throws Exception { } private void ensureSecurityManager() { WebSecurityManager securityManager = getSecurityManager(); if (securityManager == null) { log.info("No SecurityManager configured.Creating default."); securityManager = createDefaultSecurityManager(); setSecurityManager(securityManager); } } protected WebSecurityManager createDefaultSecurityManager() { return new DefaultWebSecurityManager(); } protected boolean isHttpSessions() { return getSecurityManager().isHttpSessionMode(); } protected ServletRequest wrapServletRequest(HttpServletRequest orig) { return new SecurityHttpServletRequest(orig, getServletContext(), isHttpSessions()); } @SuppressWarnings({"UnusedDeclaration"}) protected ServletRequest prepareServletRequest(ServletRequest request, ServletResponse response, FilterChain chain) { ServletRequest toUse = request; if (request instanceof HttpServletRequest) { HttpServletRequest http = (HttpServletRequest) request; toUse = wrapServletRequest(http); } return toUse; } protected ServletResponse wrapServletResponse(HttpServletResponse orig, SecurityHttpServletRequest request) { return new SecurityHttpServletResponse(orig, getServletContext(), request); } @SuppressWarnings({"UnusedDeclaration"}) protected ServletResponse prepareServletResponse(ServletRequest request, ServletResponse response, FilterChain chain) { ServletResponse toUse = response; if (!isHttpSessions() && (request instanceof SecurityHttpServletRequest) && (response instanceof HttpServletResponse)) { toUse = wrapServletResponse((HttpServletResponse) response, (SecurityHttpServletRequest) request); } return toUse; } protected WebSubject createSubject(ServletRequest request, ServletResponse response) { return new WebSubjectBuilder(getSecurityManager(), request, response).buildWebSubject(); } @SuppressWarnings({"UnusedDeclaration"}) protected void updateSessionLastAccessTime(ServletRequest request, ServletResponse response) { if (!isHttpSessions()) { Subject subject = SecurityUtils.getSubject(); if (subject != null) { Session session = subject.getSession(false); if (session != null) { try { session.touch(); } catch (Throwable t) { log.error("session.touch() method invocation has failed. Unable to update" + "the corresponding session's last access time based on the incoming request.", t); } } } } } /** * @param servletRequest the incoming {@code ServletRequest} * @param servletResponse the outgoing {@code ServletResponse} * @param chain the container-provided {@code FilterChain} to execute * @throws java.io.IOException if an IO error occurs * @throws javax.servlet.ServletException if an Throwable other than an IOException */ protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain) throws ServletException, IOException { Throwable t = null; try { //处理标准请求 final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain); //处理标准请求 final ServletResponse response = prepareServletResponse(request, servletResponse, chain); final Subject subject = createSubject(request, response); subject.execute(new Callable() { public Object call() throws Exception { updateSessionLastAccessTime(request, response); executeChain(request, response, chain); return null; } }); } catch (ExecutionException ex) { t = ex.getCause(); } catch (Throwable throwable) { t = throwable; } if (t != null) { if (t instanceof ServletException) { throw (ServletException) t; } if (t instanceof IOException) { throw (IOException) t; } String msg = "Filtered request failed."; throw new ServletException(msg, t); } } protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) { FilterChain chain = origChain; FilterChainResolver resolver = getFilterChainResolver(); if (resolver == null) { if (log.isDebugEnabled()) { log.debug("No FilterChainResolver configured. Returning original FilterChain."); } return origChain; } FilterChain resolved = resolver.getChain(request, response, origChain); if (resolved != null) { if (log.isTraceEnabled()) { log.trace("Resolved a configured FilterChain for the current request."); } chain = resolved; } else { if (log.isTraceEnabled()) { log.trace("No FilterChain configured for the current request. Using the default."); } } return chain; } /** * @param request the incoming ServletRequest * @param response the outgoing ServletResponse * @param origChain the Servlet Container-provided chain that may be wrapped further by an application-configured * chain of Filters. * @throws java.io.IOException if the underlying {@code chain.doFilter} call results in an IOException * @throws javax.servlet.ServletException if the underlying {@code chain.doFilter} call results in a ServletException * @since 1.0 */ protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain) throws IOException, ServletException { FilterChain chain = getExecutionChain(request, response, origChain); chain.doFilter(request, response); } }