Add FilterChainProxy discussion.
This commit is contained in:
parent
f57b1b9a8f
commit
436d37c166
|
@ -193,7 +193,8 @@
|
||||||
|
|
||||||
<para><mediaobject>
|
<para><mediaobject>
|
||||||
<imageobject role="html">
|
<imageobject role="html">
|
||||||
<imagedata align="center" fileref="images/SecurityInterception.gif"
|
<imagedata align="center"
|
||||||
|
fileref="images/SecurityInterception.gif"
|
||||||
format="GIF" />
|
format="GIF" />
|
||||||
</imageobject>
|
</imageobject>
|
||||||
|
|
||||||
|
@ -344,7 +345,8 @@
|
||||||
|
|
||||||
<para><mediaobject>
|
<para><mediaobject>
|
||||||
<imageobject role="html">
|
<imageobject role="html">
|
||||||
<imagedata align="center" fileref="images/Context.gif" format="GIF" />
|
<imagedata align="center" fileref="images/Context.gif"
|
||||||
|
format="GIF" />
|
||||||
</imageobject>
|
</imageobject>
|
||||||
|
|
||||||
<caption>
|
<caption>
|
||||||
|
@ -1716,7 +1718,8 @@ public boolean supports(Class clazz);</programlisting></para>
|
||||||
|
|
||||||
<para><mediaobject>
|
<para><mediaobject>
|
||||||
<imageobject role="html">
|
<imageobject role="html">
|
||||||
<imagedata align="center" fileref="images/AccessDecisionVoting.gif"
|
<imagedata align="center"
|
||||||
|
fileref="images/AccessDecisionVoting.gif"
|
||||||
format="GIF" />
|
format="GIF" />
|
||||||
</imageobject>
|
</imageobject>
|
||||||
|
|
||||||
|
@ -3795,7 +3798,8 @@ $CATALINA_HOME/bin/startup.sh</programlisting></para>
|
||||||
|
|
||||||
<para><mediaobject>
|
<para><mediaobject>
|
||||||
<imageobject role="html">
|
<imageobject role="html">
|
||||||
<imagedata align="center" fileref="images/ACLSecurity.gif" format="GIF" />
|
<imagedata align="center" fileref="images/ACLSecurity.gif"
|
||||||
|
format="GIF" />
|
||||||
</imageobject>
|
</imageobject>
|
||||||
|
|
||||||
<caption>
|
<caption>
|
||||||
|
@ -4156,6 +4160,99 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
|
||||||
WebApplicationContextUtils.getWebApplicationContext(ServletContext)</literal>,
|
WebApplicationContextUtils.getWebApplicationContext(ServletContext)</literal>,
|
||||||
so you should configure a <literal>ContextLoaderListener</literal> in
|
so you should configure a <literal>ContextLoaderListener</literal> in
|
||||||
<literal>web.xml</literal>.</para>
|
<literal>web.xml</literal>.</para>
|
||||||
|
|
||||||
|
<para>There is a lifecycle issue to consider when hosting
|
||||||
|
<literal>Filter</literal>s in an IoC container instead of a servlet
|
||||||
|
container. Specifically, which container should be responsible for
|
||||||
|
calling the <literal>Filter</literal>'s "startup" and "shutdown"
|
||||||
|
methods? It is noted that the order of initialization and destruction
|
||||||
|
of a <literal>Filter</literal> can vary by servlet container, and this
|
||||||
|
can cause problems if one <literal>Filter</literal> depends on
|
||||||
|
configuration settings established by an earlier initialized
|
||||||
|
<literal>Filter</literal>. The Spring IoC container on the other hand
|
||||||
|
has more comprehensive lifecycle/IoC interfaces (such as
|
||||||
|
<literal>InitializingBean</literal>,
|
||||||
|
<literal>DisposableBean</literal>, <literal>BeanNameAware</literal>,
|
||||||
|
<literal>ApplicationContextAware</literal> and many others) as well as
|
||||||
|
a well-understood interface contract, predictable method invocation
|
||||||
|
ordering, autowiring support, and even options to avoid implementing
|
||||||
|
Spring interfaces (eg the <literal>destroy-method</literal> attribute
|
||||||
|
in Spring XML). For this reason we recommend the use of Spring
|
||||||
|
lifecycle services instead of servlet container lifecycle services
|
||||||
|
wherever possible. By default <literal>FilterToBeanProxy</literal>
|
||||||
|
will not delegate <literal>init(FilterConfig)</literal> and
|
||||||
|
<literal>destroy()</literal> methods through to the proxied bean. If
|
||||||
|
you do require such invocations to be delegated, set the
|
||||||
|
<literal>lifecycle</literal> initialization parameter to
|
||||||
|
<literal>servlet-container-managed</literal>.</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="security-filters-filterchainproxy">
|
||||||
|
<title>FilterChainProxy</title>
|
||||||
|
|
||||||
|
<para>Whilst <literal>FilterToBeanProxy</literal> is a very useful
|
||||||
|
class, the problem is that the lines of code required for
|
||||||
|
<literal><filter></literal> and
|
||||||
|
<literal><filter-mapping></literal> entries in
|
||||||
|
<literal>web.xml</literal> explodes when using more than a few
|
||||||
|
filters. To overcome this issue, Acegi Security provides a
|
||||||
|
<literal>FilterChainProxy</literal> class. It is wired using a
|
||||||
|
<literal>FilterToBeanProxy</literal> (just like in the example above),
|
||||||
|
but the target class is
|
||||||
|
<literal>net.sf.acegisecurity.util.FilterChainProxy</literal>. The
|
||||||
|
filter chain is then declared in the application context, using code
|
||||||
|
such as this:</para>
|
||||||
|
|
||||||
|
<para><programlisting><bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
|
||||||
|
<property name="filterInvocationDefinitionSource">
|
||||||
|
<value>
|
||||||
|
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||||
|
PATTERN_TYPE_APACHE_ANT
|
||||||
|
/webServices/**=basicProcessingFilter,httpSessionIntegrationFilter,securityEnforcementFilter
|
||||||
|
/**=authenticationProcessingFilter,httpSessionIntegrationFilter,securityEnforcementFilter
|
||||||
|
</value>
|
||||||
|
</property>
|
||||||
|
</bean></programlisting></para>
|
||||||
|
|
||||||
|
<para>You may notice similarities with the way
|
||||||
|
<literal>SecurityEnforcementFilter</literal> is declared. Both regular
|
||||||
|
expressions and Ant Paths are supported, and the most specific URIs
|
||||||
|
appear first. At runtime the <literal>FilterChainProxy</literal> will
|
||||||
|
locate the first URI pattern that matches the current web request.
|
||||||
|
Each of the corresponding configuration attributes represent the name
|
||||||
|
of a bean defined in the application context. The filters will then be
|
||||||
|
invoked in the order they are specified, with standard
|
||||||
|
<literal>FilterChain</literal> behaviour being respected (a
|
||||||
|
<literal>Filter</literal> can elect not to proceed with the chain if
|
||||||
|
it wishes to end processing).</para>
|
||||||
|
|
||||||
|
<para>As you can see, <literal>FitlerChainProxy</literal> requires the
|
||||||
|
duplication of filter names for different request patterns (in the
|
||||||
|
above example, <literal>httpSessionIntegrationFilter</literal> and
|
||||||
|
<literal>securityEnforcementFilter</literal> are duplicated). This
|
||||||
|
design decision was made to enable <literal>FilterChainProxy</literal>
|
||||||
|
to specify different <literal>Filter</literal> invocation orders for
|
||||||
|
different URI patterns, and also to improve both the expressiveness
|
||||||
|
(in terms of regular expressions, Ant Paths, and any custom
|
||||||
|
<literal>FilterInvocationDefinitionSource</literal> implementations)
|
||||||
|
and clarity of which <literal>Filter</literal>s should be
|
||||||
|
invoked.</para>
|
||||||
|
|
||||||
|
<para>In relation to lifecycle issues, the
|
||||||
|
<literal>FilterChainProxy</literal> will always delegate
|
||||||
|
<literal>init(FilterConfig)</literal> and <literal>destroy()</literal>
|
||||||
|
methods through to the underlaying <literal>Filter</literal>s if such
|
||||||
|
methods are called against <literal>FilterChainProxy</literal> itself.
|
||||||
|
In this case, <literal>FilterChainProxy</literal> guarantees to only
|
||||||
|
initialize and destroy each <literal>Filter</literal> once,
|
||||||
|
irrespective of how many times it is declared by the
|
||||||
|
<literal>FilterInvocationDefinitionSource</literal>. You control the
|
||||||
|
overall choice as to whether these methods are called or not via the
|
||||||
|
<literal>lifecycle</literal> initialization parameter of the
|
||||||
|
<literal>FilterToBeanProxy</literal> that proxies
|
||||||
|
<literal>FilterChainProxy</literal>. As discussed above, by default
|
||||||
|
any servlet container lifecycle invocations are not delegated through
|
||||||
|
to <literal>FilterChainProxy</literal>.</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="security-filters-order">
|
<sect2 id="security-filters-order">
|
||||||
|
@ -4201,8 +4298,13 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
|
|
||||||
<para>All of the above filters use
|
<para>All of the above filters use
|
||||||
<literal>FilterToBeanProxy</literal>, which is discussed in the
|
<literal>FilterToBeanProxy</literal> or
|
||||||
previous section.</para>
|
<literal>FilterChainProxy</literal>, which is discussed in the
|
||||||
|
previous sections. It is recommended that a single
|
||||||
|
<literal>FilterToBeProxy</literal> proxy through to a single
|
||||||
|
<literal>FilterChainProxy</literal> for each application, with that
|
||||||
|
<literal>FilterChainProxy</literal> defining all of the Acegi Security
|
||||||
|
<literal>Filter</literal>s.</para>
|
||||||
|
|
||||||
<para>If you're using SiteMesh, ensure the Acegi Security filters
|
<para>If you're using SiteMesh, ensure the Acegi Security filters
|
||||||
execute before the SiteMesh filters are called. This enables the
|
execute before the SiteMesh filters are called. This enables the
|
||||||
|
|
Loading…
Reference in New Issue