Web support module for Apache Shiro providing servlet filters, session management, and web-specific authentication and authorization features
—
Comprehensive servlet filter system providing the foundation for Apache Shiro's web security functionality. These filters handle request processing, provide template patterns for security operations, and integrate seamlessly with servlet containers while maintaining Shiro's security context throughout the request lifecycle.
Core servlet filters that serve as entry points for Shiro security processing in web applications.
class ShiroFilter extends AbstractShiroFilter {
/**
* Creates a new ShiroFilter that uses ServletContext-configured WebEnvironment.
*/
public ShiroFilter();
/**
* Initializes the filter by retrieving the WebEnvironment from ServletContext.
* The WebEnvironment should be configured by EnvironmentLoaderListener.
*
* @throws ServletException if WebEnvironment is not found in ServletContext
*/
public void init() throws ServletException;
}class IniShiroFilter extends AbstractShiroFilter {
/** Default INI resource path */
public static final String DEFAULT_WEB_INI_RESOURCE_PATH = "/WEB-INF/shiro.ini";
/**
* Creates a new IniShiroFilter using default INI resource path.
*/
public IniShiroFilter();
/**
* Returns the configuration resource locations.
*
* @return array of configuration resource paths
*/
public String[] getConfigPath();
/**
* Sets the configuration resource locations.
*
* @param configPath array of configuration resource paths
*/
public void setConfigPath(String[] configPath);
/**
* Initializes the filter by loading configuration from INI resources.
*
* @throws ServletException if initialization fails
*/
public void init() throws ServletException;
}Base classes providing template patterns and common functionality for Shiro servlet filters.
abstract class AbstractShiroFilter extends OncePerRequestFilter {
/** ServletContext attribute key for storing WebEnvironment */
public static final String STATIC_INIT_PARAM_NAME = "staticSecurityManagerEnabled";
/**
* Returns the WebSecurityManager used by this filter.
*
* @return the WebSecurityManager instance
*/
public WebSecurityManager getSecurityManager();
/**
* Sets the WebSecurityManager for this filter.
*
* @param securityManager the WebSecurityManager to set
*/
public void setSecurityManager(WebSecurityManager securityManager);
/**
* Returns the FilterChainResolver used to resolve filter chains.
*
* @return the FilterChainResolver instance
*/
public FilterChainResolver getFilterChainResolver();
/**
* Sets the FilterChainResolver for this filter.
*
* @param filterChainResolver the FilterChainResolver to set
*/
public void setFilterChainResolver(FilterChainResolver filterChainResolver);
/**
* Returns whether static SecurityManager access is enabled.
*
* @return true if static SecurityManager is enabled
*/
public boolean isStaticSecurityManagerEnabled();
/**
* Sets whether static SecurityManager access is enabled.
*
* @param staticSecurityManagerEnabled true to enable static SecurityManager
*/
public void setStaticSecurityManagerEnabled(boolean staticSecurityManagerEnabled);
/**
* Sets the configuration for this filter.
*
* @param config the ShiroFilterConfiguration to set
*/
public void setShiroFilterConfiguration(ShiroFilterConfiguration config);
/**
* Template method for processing web requests with Shiro security.
*
* @param request the servlet request
* @param response the servlet response
* @param chain the filter chain
* @throws ServletException if servlet processing fails
* @throws IOException if I/O error occurs
*/
protected void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
throws ServletException, IOException;
/**
* Creates a Subject instance for the current request.
*
* @param request the servlet request
* @param response the servlet response
* @return the created Subject instance
*/
protected WebSubject createSubject(ServletRequest request, ServletResponse response);
/**
* Updates the session last access time if needed.
*
* @param request the servlet request
* @param response the servlet response
*/
protected void updateSessionLastAccessTime(ServletRequest request, ServletResponse response);
}abstract class OncePerRequestFilter extends NameableFilter {
/** Request attribute key to mark filter execution */
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
/**
* Ensures the filter executes only once per request.
*
* @param request the servlet request
* @param response the servlet response
* @param filterChain the filter chain
* @throws ServletException if servlet processing fails
* @throws IOException if I/O error occurs
*/
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException;
/**
* Template method for actual filter processing, called only once per request.
*
* @param request the servlet request
* @param response the servlet response
* @param chain the filter chain
* @throws ServletException if servlet processing fails
* @throws IOException if I/O error occurs
*/
protected abstract void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
throws ServletException, IOException;
/**
* Returns whether this filter should execute for the given request.
*
* @param request the servlet request
* @return true if filter should execute
*/
protected boolean isEnabled(ServletRequest request, ServletResponse response);
/**
* Returns the request attribute key used to mark filter execution.
*
* @return the attribute key string
*/
private String getAlreadyFilteredAttributeName();
}abstract class AdviceFilter extends OncePerRequestFilter {
/**
* Template method providing pre-processing, actual filtering, and post-processing.
*
* @param request the servlet request
* @param response the servlet response
* @param chain the filter chain
* @throws ServletException if servlet processing fails
* @throws IOException if I/O error occurs
*/
protected void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
throws ServletException, IOException;
/**
* Pre-processing hook executed before the filter chain continues.
*
* @param request the servlet request
* @param response the servlet response
* @return true to continue with the filter chain, false to stop processing
* @throws Exception if pre-processing fails
*/
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception;
/**
* Post-processing hook executed after the filter chain completes successfully.
*
* @param request the servlet request
* @param response the servlet response
* @throws Exception if post-processing fails
*/
protected void postHandle(ServletRequest request, ServletResponse response) throws Exception;
/**
* Cleanup hook executed after request processing, regardless of success or failure.
*
* @param request the servlet request
* @param response the servlet response
* @param exception any exception that occurred during processing, or null
* @throws Exception if cleanup fails
*/
protected void afterCompletion(ServletRequest request, ServletResponse response, Exception exception)
throws Exception;
/**
* Executes the filter chain.
*
* @param request the servlet request
* @param response the servlet response
* @param chain the filter chain
* @throws Exception if chain execution fails
*/
protected void executeChain(ServletRequest request, ServletResponse response, FilterChain chain)
throws Exception;
}Foundation classes providing common servlet filter functionality and naming capabilities.
abstract class NameableFilter extends AbstractFilter {
/**
* Returns the name of this filter.
*
* @return the filter name
*/
public String getName();
/**
* Sets the name of this filter.
*
* @param name the filter name to set
*/
public void setName(String name);
/**
* Returns a string representation including the filter name.
*
* @return string representation of this filter
*/
public String toString();
}abstract class AbstractFilter implements Filter {
/**
* Default implementation that does nothing.
*
* @param filterConfig the filter configuration
* @throws ServletException if initialization fails
*/
public void init(FilterConfig filterConfig) throws ServletException;
/**
* Default implementation that does nothing.
*/
public void destroy();
/**
* Returns a string representation of this filter.
*
* @return string representation
*/
public String toString();
}Filters that can be configured to apply different behavior based on request paths using Ant-style path patterns.
abstract class PathMatchingFilter extends AdviceFilter implements PathConfigProcessor {
/** Log instance for this class */
private static final Logger log = LoggerFactory.getLogger(PathMatchingFilter.class);
/**
* Returns the path patterns and their associated configuration.
*
* @return Map of path patterns to configuration
*/
protected Map<String, Object> getPathConfigMap();
/**
* Sets the path patterns and their associated configuration.
*
* @param pathConfigMap Map of path patterns to configuration
*/
protected void setPathConfigMap(Map<String, Object> pathConfigMap);
/**
* Returns the path-specific configuration for the current request.
*
* @param request the servlet request
* @param response the servlet response
* @return the configuration object for the matching path
*/
protected Object getPathConfig(ServletRequest request, ServletResponse response);
/**
* Determines if the request path matches any configured patterns.
*
* @param path the request path
* @param request the servlet request
* @return true if path matches a configured pattern
*/
protected boolean pathsMatch(String path, ServletRequest request);
/**
* Returns the request path for pattern matching.
*
* @param request the servlet request
* @return the request path
*/
protected String getPathWithinApplication(ServletRequest request);
/**
* Pre-processing that applies path-specific configuration.
*
* @param request the servlet request
* @param response the servlet response
* @return true to continue processing
* @throws Exception if pre-processing fails
*/
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception;
/**
* Template method called when a request matches a configured path pattern.
*
* @param request the servlet request
* @param response the servlet response
* @param mappedValue the configuration associated with the matched path
* @return true to continue processing
* @throws Exception if processing fails
*/
protected abstract boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception;
/**
* Processes path-specific configuration strings.
*
* @param path the path pattern
* @param config the configuration string
* @return the processed configuration object
*/
public Object processPathConfig(String path, String config);
}Base class for filters that control access to resources, providing login URL management and request saving/restoration functionality.
abstract class AccessControlFilter extends PathMatchingFilter {
/** Default login URL */
public static final String DEFAULT_LOGIN_URL = "/login";
/** Request parameter name for original request URL */
public static final String DEFAULT_SUCCESS_URL_PARAM = "successUrl";
/**
* Returns the login URL.
*
* @return the login URL
*/
public String getLoginUrl();
/**
* Sets the login URL.
*
* @param loginUrl the login URL to set
*/
public void setLoginUrl(String loginUrl);
/**
* Handles request processing by checking access permissions.
*
* @param request the servlet request
* @param response the servlet response
* @param mappedValue the configuration for this path
* @return true to continue processing
* @throws Exception if processing fails
*/
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception;
/**
* Determines if access is allowed for the current request.
*
* @param request the servlet request
* @param response the servlet response
* @param mappedValue the configuration for this path
* @return true if access is allowed
* @throws Exception if access check fails
*/
protected abstract boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception;
/**
* Handles the case when access is denied.
*
* @param request the servlet request
* @param response the servlet response
* @return true if the denial was handled and processing should continue
* @throws Exception if handling access denial fails
*/
protected abstract boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception;
/**
* Saves the current request and redirects to the login URL.
*
* @param request the servlet request
* @param response the servlet response
* @throws IOException if redirect fails
*/
protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response)
throws IOException;
/**
* Saves the current request for later restoration.
*
* @param request the servlet request
*/
protected void saveRequest(ServletRequest request);
/**
* Redirects to the login URL.
*
* @param request the servlet request
* @param response the servlet response
* @throws IOException if redirect fails
*/
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException;
/**
* Returns the URL to redirect to after successful login.
*
* @param request the servlet request
* @param response the servlet response
* @param mappedValue the configuration for this path
* @return the success URL
*/
protected String getSuccessUrl(ServletRequest request, ServletResponse response, Object mappedValue);
}Filter for blocking potentially malicious requests based on various security criteria.
class InvalidRequestFilter extends AccessControlFilter {
/**
* Creates a new InvalidRequestFilter with default settings.
*/
public InvalidRequestFilter();
/**
* Determines if the request is valid and access should be allowed.
*
* @param request the servlet request
* @param response the servlet response
* @param mappedValue the configuration for this path
* @return false if request appears invalid
* @throws Exception if validation fails
*/
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception;
/**
* Handles invalid requests by sending an error response.
*
* @param request the servlet request
* @param response the servlet response
* @return false to stop further processing
* @throws Exception if error handling fails
*/
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception;
/**
* Checks if the request contains potentially malicious content.
*
* @param request the servlet request
* @return true if request appears malicious
*/
private boolean containsSemicolon(ServletRequest request);
/**
* Checks if the request contains backslash characters.
*
* @param request the servlet request
* @return true if request contains backslashes
*/
private boolean containsBackslash(ServletRequest request);
/**
* Checks if the request contains non-ASCII characters.
*
* @param request the servlet request
* @return true if request contains non-ASCII characters
*/
private boolean containsNonAsciiCharacters(ServletRequest request);
}// web.xml configuration
/*
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
*/
// Programmatic filter setup
public void configureFilter(ServletContext servletContext) {
ShiroFilter shiroFilter = new ShiroFilter();
FilterRegistration.Dynamic registration = servletContext.addFilter("ShiroFilter", shiroFilter);
registration.setInitParameter("staticSecurityManagerEnabled", "false");
registration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ERROR),
false, "/*");
}public class CustomSecurityFilter extends AccessControlFilter {
private String customLoginUrl = "/custom-login";
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
Subject subject = getSubject(request, response);
// Custom access logic
return subject.isAuthenticated() && subject.hasRole("custom-role");
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
return true; // Allow login requests through
} else {
saveRequestAndRedirectToLogin(request, response);
return false;
}
}
private boolean isLoginRequest(ServletRequest request, ServletResponse response) {
return pathsMatch(customLoginUrl, request);
}
@Override
public String getLoginUrl() {
return customLoginUrl;
}
}public class FilterChainConfig {
public void setupFilterChains() {
DefaultFilterChainManager manager = new DefaultFilterChainManager();
// Add custom filters
manager.addFilter("custom", new CustomSecurityFilter());
manager.addFilter("invalidRequest", new InvalidRequestFilter());
// Create filter chains
manager.createChain("/api/**", "invalidRequest, authc, perms[api:read]");
manager.createChain("/admin/**", "authc, roles[admin]");
manager.createChain("/custom/**", "custom");
manager.createChain("/**", "anon");
// Use with PathMatchingFilterChainResolver
PathMatchingFilterChainResolver resolver = new PathMatchingFilterChainResolver();
resolver.setFilterChainManager(manager);
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-apache-shiro--shiro-web