001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.web.filter.mgt;
020
021 import org.apache.shiro.config.ConfigurationException;
022
023 import javax.servlet.Filter;
024 import javax.servlet.FilterChain;
025 import java.util.Map;
026 import java.util.Set;
027
028 /**
029 * A {@code FilterChainManager} manages the creation and modification of {@link Filter} chains from an available pool
030 * of {@link Filter} instances.
031 *
032 * @since 1.0
033 */
034 public interface FilterChainManager {
035
036 /**
037 * Returns the pool of available {@code Filter}s managed by this manager, keyed by {@code name}.
038 *
039 * @return the pool of available {@code Filter}s managed by this manager, keyed by {@code name}.
040 */
041 Map<String, Filter> getFilters();
042
043 /**
044 * Returns the filter chain identified by the specified {@code chainName} or {@code null} if there is no chain with
045 * that name.
046 *
047 * @param chainName the name identifying the filter chain.
048 * @return the filter chain identified by the specified {@code chainName} or {@code null} if there is no chain with
049 * that name.
050 */
051 NamedFilterList getChain(String chainName);
052
053 /**
054 * Returns {@code true} if one or more configured chains are available, {@code false} if none are configured.
055 *
056 * @return {@code true} if one or more configured chains are available, {@code false} if none are configured.
057 */
058 boolean hasChains();
059
060 /**
061 * Returns the names of all configured chains or an empty {@code Set} if no chains have been configured.
062 *
063 * @return the names of all configured chains or an empty {@code Set} if no chains have been configured.
064 */
065 Set<String> getChainNames();
066
067 /**
068 * Proxies the specified {@code original} FilterChain with the named chain. The returned
069 * {@code FilterChain} instance will first execute the configured named chain and then lastly invoke the given
070 * {@code original} chain.
071 *
072 * @param original the original FilterChain to proxy
073 * @param chainName the name of the internal configured filter chain that should 'sit in front' of the specified
074 * original chain.
075 * @return a {@code FilterChain} instance that will execute the named chain and then finally the
076 * specified {@code original} FilterChain instance.
077 * @throws IllegalArgumentException if there is no configured chain with the given {@code chainName}.
078 */
079 FilterChain proxy(FilterChain original, String chainName);
080
081 /**
082 * Adds a filter to the 'pool' of available filters that can be used when
083 * {@link #addToChain(String, String, String) creating filter chains}.
084 * <p/>
085 * Calling this method is effectively the same as calling
086 * <code>{@link #addFilter(String, javax.servlet.Filter, boolean) addFilter}(name, filter, <b>true</b>);</code>
087 *
088 * @param name the name to assign to the filter, used to reference the filter in chain definitions
089 * @param filter the filter to initialize and then add to the pool of available filters that can be used
090 */
091 void addFilter(String name, Filter filter);
092
093 /**
094 * Adds a filter to the 'pool' of available filters that can be used when
095 * {@link #addToChain(String, String, String) creating filter chains}.
096 *
097 * @param name the name to assign to the filter, used to reference the filter in chain definitions
098 * @param filter the filter to assign to the filter pool
099 * @param init whether or not the {@code Filter} should be
100 * {@link Filter#init(javax.servlet.FilterConfig) initialized} first before being added to the pool.
101 */
102 void addFilter(String name, Filter filter, boolean init);
103
104 /**
105 * Creates a filter chain for the given {@code chainName} with the specified {@code chainDefinition}
106 * String.
107 * <h3>Conventional Use</h3>
108 * Because the {@code FilterChainManager} interface does not impose any restrictions on filter chain names,
109 * (it expects only Strings), a convenient convention is to make the chain name an actual URL path expression
110 * (such as an {@link org.apache.shiro.util.AntPathMatcher Ant path expression}). For example:
111 * <p/>
112 * <code>createChain(<b><em>path_expression</em></b>, <em>path_specific_filter_chain_definition</em>);</code>
113 * This convention can be used by a {@link FilterChainResolver} to inspect request URL paths
114 * against the chain name (path) and, if a match is found, return the corresponding chain for runtime filtering.
115 * <h3>Chain Definition Format</h3>
116 * The {@code chainDefinition} method argument is expected to conform to the following format:
117 * <pre>
118 * filter1[optional_config1], filter2[optional_config2], ..., filterN[optional_configN]</pre>
119 * where
120 * <ol>
121 * <li>{@code filterN} is the name of a filter previously
122 * {@link #addFilter(String, javax.servlet.Filter) registered} with the manager, and</li>
123 * <li>{@code [optional_configN]} is an optional bracketed string that has meaning for that particular filter for
124 * <em>this particular chain</em></li>
125 * </ol>
126 * If the filter does not need specific config for that chain name/URL path,
127 * you may discard the brackets - that is, {@code filterN[]} just becomes {@code filterN}.
128 * <p/>
129 * And because this method does create a chain, remember that order matters! The comma-delimited filter tokens in
130 * the {@code chainDefinition} specify the chain's execution order.
131 * <h3>Examples</h3>
132 * <pre>/account/** = authcBasic</pre>
133 * This example says "Create a filter named '{@code /account/**}' consisting of only the '{@code authcBasic}'
134 * filter". Also because the {@code authcBasic} filter does not need any path-specific
135 * config, it doesn't have any config brackets {@code []}.
136 * <p/>
137 * <pre>/remoting/** = authcBasic, roles[b2bClient], perms["remote:invoke:wan,lan"]</pre>
138 * This example by contrast uses the 'roles' and 'perms' filters which <em>do</em> use bracket notation. This
139 * definition says:
140 * <p/>
141 * Construct a filter chain named '{@code /remoting/**}' which
142 * <ol>
143 * <li>ensures the user is first authenticated ({@code authcBasic}) then</li>
144 * <li>ensures that user has the {@code b2bClient} role, and then finally</li>
145 * <li>ensures that they have the {@code remote:invoke:lan,wan} permission.</li>
146 * </ol>
147 * <p/>
148 * <b>Note</b>: because elements within brackets [ ] can be comma-delimited themselves, you must quote the
149 * internal bracket definition if commas are needed (the above example has 'lan,wan'). If we didn't do that, the
150 * parser would interpret the chain definition as four tokens:
151 * <ol>
152 * <li>authcBasic</li>
153 * <li>roles[b2bclient]</li>
154 * <li>perms[remote:invoke:lan</li>
155 * <li>wan]</li>
156 * </ol>
157 * which is obviously incorrect. So remember to use quotes if your internal bracket definitions need to use commas.
158 *
159 * @param chainName the name to associate with the chain, conventionally a URL path pattern.
160 * @param chainDefinition the string-formatted chain definition used to construct an actual
161 * {@link NamedFilterList} chain instance.
162 * @see FilterChainResolver
163 * @see org.apache.shiro.util.AntPathMatcher AntPathMatcher
164 */
165 void createChain(String chainName, String chainDefinition);
166
167 /**
168 * Adds (appends) a filter to the filter chain identified by the given {@code chainName}. If there is no chain
169 * with the given name, a new one is created and the filter will be the first in the chain.
170 *
171 * @param chainName the name of the chain where the filter will be appended.
172 * @param filterName the name of the {@link #addFilter registered} filter to add to the chain.
173 * @throws IllegalArgumentException if there is not a {@link #addFilter(String, javax.servlet.Filter) registered}
174 * filter under the given {@code filterName}
175 */
176 void addToChain(String chainName, String filterName);
177
178 /**
179 * Adds (appends) a filter to the filter chain identified by the given {@code chainName}. If there is no chain
180 * with the given name, a new one is created and the filter will be the first in the chain.
181 * <p/>
182 * Note that the final argument expects the associated filter to be an instance of
183 * a {@link org.apache.shiro.web.filter.PathConfigProcessor PathConfigProcessor} to accept per-chain configuration.
184 * If it is not, a {@link IllegalArgumentException} will be thrown.
185 *
186 * @param chainName the name of the chain where the filter will be appended.
187 * @param filterName the name of the {@link #addFilter registered} filter to add to the chain.
188 * @param chainSpecificFilterConfig the filter-specific configuration that should be applied for only the specified
189 * filter chain.
190 * @throws IllegalArgumentException if there is not a {@link #addFilter(String, javax.servlet.Filter) registered}
191 * filter under the given {@code filterName}
192 * @throws ConfigurationException if the filter is not capable of accepting {@code chainSpecificFilterConfig}
193 * (usually such filters implement the
194 * {@link org.apache.shiro.web.filter.PathConfigProcessor PathConfigProcessor}
195 * interface).
196 */
197 void addToChain(String chainName, String filterName, String chainSpecificFilterConfig) throws ConfigurationException;
198 }