Web support module for Apache Shiro providing servlet filters, session management, and web-specific authentication and authorization features
—
Components for managing and resolving filter chains in Apache Shiro web applications. These classes handle the registration, configuration, and resolution of servlet filter chains based on URL patterns, enabling flexible and powerful security policy configuration.
Core interfaces and implementations for resolving filter chains based on incoming requests and URL patterns.
interface FilterChainResolver {
/**
* Resolves and returns the filter chain for the given request.
*
* @param request the incoming servlet request
* @param response the servlet response
* @param originalChain the original filter chain from the servlet container
* @return the resolved filter chain or originalChain if no specific chain found
*/
FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain);
}class PathMatchingFilterChainResolver implements FilterChainResolver {
/**
* Creates a new PathMatchingFilterChainResolver.
*/
public PathMatchingFilterChainResolver();
/**
* Returns the FilterChainManager used to manage filter chains.
*
* @return the FilterChainManager instance
*/
public FilterChainManager getFilterChainManager();
/**
* Sets the FilterChainManager to use for managing filter chains.
*
* @param filterChainManager the FilterChainManager to set
*/
public void setFilterChainManager(FilterChainManager filterChainManager);
/**
* Resolves the filter chain by matching the request path against configured patterns.
*
* @param request the servlet request
* @param response the servlet response
* @param originalChain the original filter chain
* @return the matching filter chain or originalChain if no match
*/
public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain);
/**
* Returns the request path used for pattern matching.
*
* @param request the servlet request
* @return the request path within the application
*/
protected String getPathWithinApplication(ServletRequest request);
}Interfaces and implementations for managing named filter chains and their configurations.
interface FilterChainManager extends FilterManager {
/**
* Returns all configured filter chains.
*
* @return Map of chain names to NamedFilterList instances
*/
Map<String, NamedFilterList> getFilterChains();
/**
* Returns whether any filter chains have been configured.
*
* @return true if chains exist
*/
boolean hasChains();
/**
* Returns the filter chain with the specified name.
*
* @param chainName the name of the chain to retrieve
* @return the NamedFilterList for the specified chain name
*/
NamedFilterList getChain(String chainName);
/**
* Creates a new filter chain with the specified name and configuration.
*
* @param chainName the name of the chain to create
* @param chainDefinition the chain configuration string
* @return the created NamedFilterList
*/
NamedFilterList createChain(String chainName, String chainDefinition);
/**
* Adds a filter to the specified chain.
*
* @param chainName the name of the chain
* @param filterName the name of the filter to add
*/
void addToChain(String chainName, String filterName);
/**
* Adds a filter to the specified chain with configuration.
*
* @param chainName the name of the chain
* @param filterName the name of the filter to add
* @param chainSpecificFilterConfig filter-specific configuration
*/
void addToChain(String chainName, String filterName, String chainSpecificFilterConfig);
/**
* Creates a filter chain from the given definition string.
*
* @param chainName the name of the chain
* @param chainDefinition comma-delimited filter names with optional configs
* @return the created NamedFilterList
*/
NamedFilterList createChain(String chainName, String chainDefinition);
}class DefaultFilterChainManager extends AbstractFilterChainManager {
/**
* Creates a new DefaultFilterChainManager with default filters.
*/
public DefaultFilterChainManager();
/**
* Creates a new DefaultFilterChainManager with the specified FilterConfig.
*
* @param filterConfig the FilterConfig for initializing filters
*/
public DefaultFilterChainManager(FilterConfig filterConfig);
/**
* Returns all configured filter chains.
*
* @return Map of chain names to filter chains
*/
public Map<String, NamedFilterList> getFilterChains();
/**
* Returns whether any filter chains exist.
*
* @return true if chains are configured
*/
public boolean hasChains();
/**
* Returns the filter chain with the specified name.
*
* @param chainName the chain name
* @return the NamedFilterList or null if not found
*/
public NamedFilterList getChain(String chainName);
/**
* Creates a filter chain from the definition string.
*
* @param chainName the name for the chain
* @param chainDefinition comma-delimited filter configuration
* @return the created NamedFilterList
*/
public NamedFilterList createChain(String chainName, String chainDefinition);
/**
* Adds a filter to the specified chain.
*
* @param chainName the chain name
* @param filterName the filter name to add
*/
public void addToChain(String chainName, String filterName);
/**
* Adds a filter to the specified chain with configuration.
*
* @param chainName the chain name
* @param filterName the filter name to add
* @param chainSpecificFilterConfig the filter configuration
*/
public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig);
/**
* Creates default filter instances for common Shiro filters.
*
* @return Map of filter names to Filter instances
*/
protected Map<String, Filter> createDefaultFilters();
/**
* Adds default filters to this manager.
*/
protected void addDefaultFilters(boolean init);
}Classes representing named collections of filters that form filter chains.
interface NamedFilterList extends List<Filter> {
/**
* Returns the name of this filter list.
*
* @return the filter list name
*/
String getName();
/**
* Creates a FilterChain that executes the filters in this list.
*
* @param originalChain the original filter chain to delegate to after processing
* @return a FilterChain that executes this list's filters
*/
FilterChain proxy(FilterChain originalChain);
}class SimpleNamedFilterList extends ArrayList<Filter> implements NamedFilterList {
/**
* Creates a new SimpleNamedFilterList with the specified name.
*
* @param name the name for this filter list
*/
public SimpleNamedFilterList(String name);
/**
* Creates a new SimpleNamedFilterList with the specified name and filters.
*
* @param name the name for this filter list
* @param filters the initial filters for this list
*/
public SimpleNamedFilterList(String name, List<Filter> filters);
/**
* Returns the name of this filter list.
*
* @return the filter list name
*/
public String getName();
/**
* Creates a proxied FilterChain that executes this list's filters.
*
* @param originalChain the original chain to execute after this list's filters
* @return a FilterChain proxy for this filter list
*/
public FilterChain proxy(FilterChain originalChain);
}Enumeration defining all built-in Shiro filters available for use in filter chains.
enum DefaultFilter {
anon(AnonymousFilter.class),
authc(FormAuthenticationFilter.class),
authcBasic(BasicHttpAuthenticationFilter.class),
authcBearer(BearerHttpAuthenticationFilter.class),
logout(LogoutFilter.class),
noSessionCreation(NoSessionCreationFilter.class),
perms(PermissionsAuthorizationFilter.class),
port(PortFilter.class),
rest(HttpMethodPermissionFilter.class),
roles(RolesAuthorizationFilter.class),
ssl(SslFilter.class),
user(UserFilter.class),
invalidRequest(InvalidRequestFilter.class);
/**
* Creates a new instance of this filter.
*
* @return a new Filter instance
*/
public Filter newInstance();
/**
* Returns the Filter class for this default filter.
*
* @return the Filter class
*/
public Class<? extends Filter> getFilterClass();
/**
* Creates a map of all default filters with their names as keys.
*
* @param filterConfig the FilterConfig for filter initialization
* @return Map of filter names to Filter instances
*/
public static Map<String, Filter> createInstanceMap(FilterConfig filterConfig);
}Abstract base classes providing common filter management functionality.
abstract class AbstractFilterChainManager implements FilterChainManager {
/**
* Returns all registered filters.
*
* @return Map of filter names to Filter instances
*/
public Map<String, Filter> getFilters();
/**
* Returns the filter with the specified name.
*
* @param name the filter name
* @return the Filter instance or null if not found
*/
public Filter getFilter(String name);
/**
* Adds a filter with the specified name.
*
* @param name the filter name
* @param filter the Filter instance
*/
public void addFilter(String name, Filter filter);
/**
* Adds a filter with the specified name and initializes it.
*
* @param name the filter name
* @param filter the Filter instance
* @param init whether to initialize the filter
*/
public void addFilter(String name, Filter filter, boolean init);
/**
* Creates a filter instance from the class name.
*
* @param className the fully qualified filter class name
* @param args constructor arguments
* @return the created Filter instance
*/
public Filter createFilter(String className, Object... args);
/**
* Initializes the specified filter.
*
* @param filter the filter to initialize
*/
protected void initFilter(Filter filter);
}public void setupBasicFilterChains() {
// Create filter chain manager
DefaultFilterChainManager manager = new DefaultFilterChainManager();
// Basic authentication and authorization chains
manager.createChain("/login", "authc");
manager.createChain("/logout", "logout");
manager.createChain("/admin/**", "authc, roles[admin]");
manager.createChain("/user/**", "authc");
manager.createChain("/api/**", "authcBasic");
manager.createChain("/**", "anon");
// Create resolver and set in filter
PathMatchingFilterChainResolver resolver = new PathMatchingFilterChainResolver();
resolver.setFilterChainManager(manager);
// Use with AbstractShiroFilter
AbstractShiroFilter shiroFilter = new ShiroFilter();
shiroFilter.setFilterChainResolver(resolver);
}public void setupAdvancedFilterChains() {
DefaultFilterChainManager manager = new DefaultFilterChainManager();
// Add custom filters
manager.addFilter("jwt", new JwtAuthenticationFilter());
manager.addFilter("cors", new CorsFilter());
manager.addFilter("rate", new RateLimitFilter());
// Complex filter chains with multiple filters and configurations
manager.createChain("/api/public/**", "cors, anon");
manager.createChain("/api/auth/**", "cors, authc");
manager.createChain("/api/admin/**", "cors, jwt, roles[admin], rate");
manager.createChain("/api/users/**", "cors, jwt, perms[user:read], rate");
// SSL requirements for sensitive areas
manager.createChain("/secure/**", "ssl, authc, roles[user]");
manager.createChain("/admin/**", "ssl, authc, roles[admin]");
// Different authentication methods for different areas
manager.createChain("/web/login", "authc"); // Form auth for web
manager.createChain("/web/**", "authc, user"); // Web interface
manager.createChain("/api/v1/**", "authcBasic"); // Basic auth for API v1
manager.createChain("/api/v2/**", "jwt"); // JWT for API v2
// Create resolver
PathMatchingFilterChainResolver resolver = new PathMatchingFilterChainResolver();
resolver.setFilterChainManager(manager);
}public class FilterChainBuilder {
private DefaultFilterChainManager manager;
public FilterChainBuilder() {
this.manager = new DefaultFilterChainManager();
}
public FilterChainBuilder addCustomFilter(String name, Filter filter) {
manager.addFilter(name, filter);
return this;
}
public FilterChainBuilder publicAccess(String pattern) {
manager.createChain(pattern, "anon");
return this;
}
public FilterChainBuilder requireAuthentication(String pattern) {
manager.createChain(pattern, "authc");
return this;
}
public FilterChainBuilder requireRole(String pattern, String role) {
manager.createChain(pattern, "authc, roles[" + role + "]");
return this;
}
public FilterChainBuilder requirePermission(String pattern, String permission) {
manager.createChain(pattern, "authc, perms[" + permission + "]");
return this;
}
public FilterChainBuilder requireSsl(String pattern) {
manager.createChain(pattern, "ssl, authc");
return this;
}
public FilterChainBuilder apiAccess(String pattern, String authType) {
String chain = "cors";
if ("basic".equals(authType)) {
chain += ", authcBasic";
} else if ("bearer".equals(authType)) {
chain += ", authcBearer";
}
manager.createChain(pattern, chain);
return this;
}
public FilterChainManager build() {
return manager;
}
}
// Usage
public void buildFilterChains() {
FilterChainBuilder builder = new FilterChainBuilder()
.addCustomFilter("audit", new AuditFilter())
.publicAccess("/css/**")
.publicAccess("/js/**")
.publicAccess("/images/**")
.requireAuthentication("/login")
.requireSsl("/admin/**")
.requireRole("/admin/**", "admin")
.requirePermission("/reports/**", "report:read")
.apiAccess("/api/v1/**", "basic")
.apiAccess("/api/v2/**", "bearer")
.publicAccess("/**");
FilterChainManager manager = builder.build();
}public class DynamicFilterChainManager {
private DefaultFilterChainManager manager;
public DynamicFilterChainManager() {
this.manager = new DefaultFilterChainManager();
}
public void addSecurityRule(String pattern, String[] roles, String[] permissions) {
StringBuilder chainDef = new StringBuilder("authc");
if (roles != null && roles.length > 0) {
chainDef.append(", roles[").append(String.join(",", roles)).append("]");
}
if (permissions != null && permissions.length > 0) {
chainDef.append(", perms[").append(String.join(",", permissions)).append("]");
}
manager.createChain(pattern, chainDef.toString());
}
public void removeSecurityRule(String pattern) {
Map<String, NamedFilterList> chains = manager.getFilterChains();
chains.remove(pattern);
}
public void updateSecurityRule(String pattern, String newChainDefinition) {
removeSecurityRule(pattern);
manager.createChain(pattern, newChainDefinition);
}
public void addMaintenanceMode() {
// Add maintenance filter to all paths except admin
manager.addFilter("maintenance", new MaintenanceFilter());
manager.createChain("/**", "maintenance, anon");
manager.createChain("/admin/**", "ssl, authc, roles[admin]");
}
public void removeMaintenance() {
// Remove maintenance mode and restore normal chains
Map<String, NamedFilterList> chains = manager.getFilterChains();
chains.clear();
setupNormalChains();
}
private void setupNormalChains() {
manager.createChain("/admin/**", "ssl, authc, roles[admin]");
manager.createChain("/user/**", "authc");
manager.createChain("/**", "anon");
}
}public class FilterChainDebugger {
public void debugFilterChains(FilterChainManager manager) {
Map<String, NamedFilterList> chains = manager.getFilterChains();
System.out.println("=== Filter Chain Configuration ===");
for (Map.Entry<String, NamedFilterList> entry : chains.entrySet()) {
String pattern = entry.getKey();
NamedFilterList filterList = entry.getValue();
System.out.printf("Pattern: %s%n", pattern);
System.out.printf(" Chain: %s%n", filterList.getName());
System.out.printf(" Filters: ");
for (Filter filter : filterList) {
System.out.printf("%s ", filter.getClass().getSimpleName());
}
System.out.println();
}
}
public boolean testPathMatching(String testPath, FilterChainManager manager) {
PathMatchingFilterChainResolver resolver = new PathMatchingFilterChainResolver();
resolver.setFilterChainManager(manager);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI(testPath);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = resolver.getChain(request, response, null);
boolean hasCustomChain = !(chain instanceof javax.servlet.FilterChain);
System.out.printf("Path '%s' -> %s%n", testPath,
hasCustomChain ? "Custom Chain" : "Default Chain");
return hasCustomChain;
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-apache-shiro--shiro-web