mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-31 17:22:13 +00:00
SEC-1584: Documentation of request-checking and matching process. Logging of servletPath and and pathInfo in DebugFilter for comparison.
This commit is contained in:
parent
0fd2c48dfb
commit
f455e9a5a4
@ -41,6 +41,8 @@ class DebugFilter extends OncePerRequestFilter {
|
||||
List<Filter> filters = getFilters(request);
|
||||
logger.log("Request received for '" + UrlUtils.buildRequestUrl(request) + "':\n\n" +
|
||||
request + "\n\n" +
|
||||
"servletPath:" + request.getServletPath() + "\n" +
|
||||
"pathInfo:" + request.getPathInfo() + "\n\n" +
|
||||
formatFilters(filters));
|
||||
|
||||
fcp.doFilter(new DebugRequestWrapper(request), response, filterChain);
|
||||
|
@ -142,17 +142,20 @@
|
||||
<literal><http></literal> element is the parent for all web-related namespace
|
||||
functionality. The <literal><intercept-url></literal> element defines a
|
||||
<literal>pattern</literal> which is matched against the URLs of incoming requests
|
||||
using an ant path style syntax. You can also use regular-expression matching as an
|
||||
alternative (see the namespace appendix for more details). The
|
||||
<literal>access</literal> attribute defines the access requirements for requests
|
||||
matching the given pattern. With the default configuration, this is typically a
|
||||
comma-separated list of roles, one of which a user must have to be allowed to make
|
||||
the request. The prefix <quote>ROLE_</quote> is a marker which indicates that a
|
||||
simple comparison with the user's authorities should be made. In other words, a
|
||||
normal role-based check should be used. Access-control in Spring Security is not
|
||||
limited to the use of simple roles (hence the use of the prefix to differentiate
|
||||
between different types of security attributes). We'll see later how the
|
||||
interpretation can vary<footnote>
|
||||
using an ant path style syntax<footnote>
|
||||
<para>See the section on <link xlink:href="#request-matching">Request
|
||||
Matching</link> in the Web Application Infrastructure chapter for more details
|
||||
on how matches are actually performed.</para>
|
||||
</footnote>. You can also use regular-expression matching as an alternative (see the
|
||||
namespace appendix for more details). The <literal>access</literal> attribute
|
||||
defines the access requirements for requests matching the given pattern. With the
|
||||
default configuration, this is typically a comma-separated list of roles, one of
|
||||
which a user must have to be allowed to make the request. The prefix
|
||||
<quote>ROLE_</quote> is a marker which indicates that a simple comparison with the
|
||||
user's authorities should be made. In other words, a normal role-based check should
|
||||
be used. Access-control in Spring Security is not limited to the use of simple roles
|
||||
(hence the use of the prefix to differentiate between different types of security
|
||||
attributes). We'll see later how the interpretation can vary<footnote>
|
||||
<para>The interpretation of the comma-separated values in the
|
||||
<literal>access</literal> attribute depends on the implementation of the <link
|
||||
xlink:href="#ns-access-manager">AccessDecisionManager</link> which is used. In
|
||||
|
@ -55,15 +55,16 @@
|
||||
</section>
|
||||
<section xml:id="filter-chain-proxy">
|
||||
<title><classname>FilterChainProxy</classname></title>
|
||||
<para> It should now be clear that you can declare each Spring Security filter bean that
|
||||
you require in your application context file and add a corresponding
|
||||
<para>Spring Security's web infrastructure should only be used by delegating to an
|
||||
instance of <classname>FilterChainProxy</classname>. The security filters should not
|
||||
be used by themselves In theory you could declare each Spring Security filter bean
|
||||
that you require in your application context file and add a corresponding
|
||||
<classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename>
|
||||
for each filter, making sure that they are ordered correctly. This is a cumbersome
|
||||
approach and clutters up the <filename>web.xml</filename> file quickly if we have a
|
||||
lot of filters. We would prefer to just add a single entry to
|
||||
<filename>web.xml</filename> and deal entirely with the application context file for
|
||||
managing our web security beans. This is where Spring Secuiryt's
|
||||
<classname>FilterChainProxy</classname> comes in. It is wired using a
|
||||
for each filter, making sure that they are ordered correctly, but this would be
|
||||
cumbersome and would clutter up the <filename>web.xml</filename> file quickly if you
|
||||
have a lot of filters. <classname>FilterChainProxy</classname> lets us add a single
|
||||
entry to <filename>web.xml</filename> and deal entirely with the application context
|
||||
file for managing our web security beans. It is wired using a
|
||||
<literal>DelegatingFilterProxy</literal>, just like in the example above, but with
|
||||
the <literal>filter-name</literal> set to the bean name
|
||||
<quote>filterChainProxy</quote>. The filter chain is then declared in the
|
||||
@ -89,8 +90,8 @@
|
||||
context XML file in order to use this syntax.</para>
|
||||
</footnote>. It maps a particular URL pattern to a chain of filters built up from
|
||||
the bean names specified in the <literal>filters</literal> element. Both regular
|
||||
expressions and Ant Paths are supported, and the most specific URIs appear first. At
|
||||
runtime the <classname>FilterChainProxy</classname> will locate the first URI
|
||||
expressions and Ant Paths are supported, and the most specific URLs appear first. At
|
||||
runtime the <classname>FilterChainProxy</classname> will locate the first URL
|
||||
pattern that matches the current web request and the list of filter beans specified
|
||||
by the <literal>filters</literal> attribute will be applied to that request. The
|
||||
filters will be invoked in the order they are defined, so you have complete control
|
||||
@ -106,18 +107,10 @@
|
||||
<classname>SecurityContextPersistenceFilter</classname> (with its default
|
||||
<literal>allowSessionCreation</literal> as <literal>true</literal>) would likely be
|
||||
sufficient.</para>
|
||||
<para>In relation to lifecycle issues, the <classname>FilterChainProxy</classname> will
|
||||
always delegate <methodname>init(FilterConfig)</methodname> and
|
||||
<methodname>destroy()</methodname> methods through to the underlaying
|
||||
<interfacename>Filter</interfacename>s if such methods are called against
|
||||
<classname>FilterChainProxy</classname> itself. In this case,
|
||||
<classname>FilterChainProxy</classname> guarantees to only initialize and destroy
|
||||
each <literal>Filter</literal> bean once, no matter how many times it is declared in
|
||||
the filter chain(s). You control the overall choice as to whether these methods are
|
||||
called or not via the <literal>targetFilterLifecycle</literal> initialization
|
||||
parameter of <literal>DelegatingFilterProxy</literal>. By default this property is
|
||||
<literal>false</literal> and servlet container lifecycle invocations are not
|
||||
delegated through <literal>DelegatingFilterProxy</literal>.</para>
|
||||
<para>Note that <classname>FilterChainProxy</classname> does not invoke standard filter
|
||||
lifecycle methods on the filters it is configured with. We recommend you use
|
||||
Spring's application context lifecycle interfaces as an alternative, just as you
|
||||
would for any other Spring bean.</para>
|
||||
<para> When we looked at how to set up web security using <link
|
||||
xlink:href="#namespace-auto-config">namespace configuration</link>, we used a
|
||||
<literal>DelegatingFilterProxy</literal> with the name
|
||||
@ -126,15 +119,15 @@
|
||||
namespace. </para>
|
||||
<section>
|
||||
<title>Bypassing the Filter Chain</title>
|
||||
<para> As with the namespace, you can use the attribute <literal>filters =
|
||||
"none"</literal> as an alternative to supplying a filter bean list. This will
|
||||
omit the request pattern from the security filter chain entirely. Note that
|
||||
anything matching this path will then have no authentication or authorization
|
||||
services applied and will be freely accessible. If you want to make use of the
|
||||
contents of the <classname>SecurityContext</classname> contents during a
|
||||
request, then it must have passed through the security filter chain. Otherwise
|
||||
the <classname>SecurityContextHolder</classname> will not have been populated
|
||||
and the contents will be null.</para>
|
||||
<para> You can use the attribute <literal>filters = "none"</literal> as an
|
||||
alternative to supplying a filter bean list. This will omit the request pattern
|
||||
from the security filter chain entirely. Note that anything matching this path
|
||||
will then have no authentication or authorization services applied and will be
|
||||
freely accessible. If you want to make use of the contents of the
|
||||
<classname>SecurityContext</classname> contents during a request, then it must
|
||||
have passed through the security filter chain. Otherwise the
|
||||
<classname>SecurityContextHolder</classname> will not have been populated and
|
||||
the contents will be null.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
@ -201,6 +194,78 @@
|
||||
</listitem>
|
||||
</orderedlist></para>
|
||||
</section>
|
||||
<section xml:id="request-matching">
|
||||
<title>Request Matching and <interfacename>HttpFirewall</interfacename></title>
|
||||
<para>Spring Security has several areas where patterns you have defined are tested
|
||||
against incoming requests in order to decide how the request should be handled. This
|
||||
occurs when the <classname>FilterChainProxy</classname> decides which filter chain a
|
||||
request should be passed through and also when the
|
||||
<classname>FilterSecurityInterceptor</classname> decides which security constraints
|
||||
apply to a request. It's important to understand what the mechanism is and what URL
|
||||
value is used when testing against the patterns that you define.</para>
|
||||
<para>The Servlet Specification defines several properties for the
|
||||
<interfacename>HttpServletRequest</interfacename> which are accessible via getter
|
||||
methods, and which we might want to match against. These are the
|
||||
<literal>contextPath</literal>, <literal>servletPath</literal>,
|
||||
<literal>pathInfo</literal> and <literal>queryString</literal>. Spring Security is
|
||||
only interested in securing paths within the application, so the
|
||||
<literal>contextPath</literal> is ignored. Unfortunately, the servlet spec does not
|
||||
define exactly what the values of <literal>servletPath</literal> and
|
||||
<literal>pathInfo</literal> will contain for a particular request URI. For example,
|
||||
each path segment of a URL may contain parameters, as defined in <link
|
||||
xlink:href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</link><footnote>
|
||||
<para>You have probably seen this when a browser doesn't support cookies and the
|
||||
<literal>jsessionid</literal> parameter is appended to the URL after a
|
||||
semi-colon. However the RFC allows the presence of these parameters in any path
|
||||
segment of the URL</para>
|
||||
</footnote>. The Specification does not clearly state whether these should be
|
||||
included in the <literal>servletPath</literal> and <literal>pathInfo</literal>
|
||||
values and the behaviour varies between different servlet containers. There is a
|
||||
danger that when an application is deployed in a container which does not strip path
|
||||
parameters from these values, an attacker could add them to the requested URL in
|
||||
order to cause a pattern match to succeed or fail unexpectedly.<footnote>
|
||||
<para>The original values will be returned once the request leaves the
|
||||
<classname>FilterChainProxy</classname>, so will still be available to the
|
||||
application.</para>
|
||||
</footnote>. Other variations in the incoming URL are also possible. For example, it
|
||||
could contain path-traversal sequences (like <literal>/../</literal>) or multiple
|
||||
forward slashes (<literal>//</literal>) which could also cause pattern-matches to
|
||||
fail. Some containers normalize these out before performing the servlet mapping, but
|
||||
others don't. To protect against issues like these,
|
||||
<classname>FilterChainProxy</classname> uses an
|
||||
<interfacename>HttpFirewall</interfacename> strategy to check and wrap the request.
|
||||
Un-normalized requests are automatically rejected by default, and path parameters
|
||||
and duplicate slashes are removed for matching purposes.<footnote>
|
||||
<para>So, for example, an original request path
|
||||
<literal>/secure;hack=1/somefile.html;hack=2</literal> will be returned as
|
||||
<literal>/secure/somefile.html</literal>.</para>
|
||||
</footnote>. It is therefore essential that a
|
||||
<classname>FilterChainProxy</classname> is used to manage the security filter chain.
|
||||
Note that the <literal>servletPath</literal> and <literal>pathInfo</literal> values
|
||||
are decoded by the container, so your application should not have any valid paths
|
||||
which contain semi-colons, as these parts will be removed for matching purposes. </para>
|
||||
<para>As mentioned above, the default strategy is to use Ant-style paths for matching
|
||||
and this is likely to be the best choice for most users. The strategy is implemented
|
||||
in the class <classname>AntPathRequestMatcher</classname> which uses Spring's
|
||||
<classname>AntPathMatcher</classname> to perform a case-insensitive match of the
|
||||
pattern against the concatenated <literal>servletPath</literal> and
|
||||
<literal>pathInfo</literal>, ignoring the <literal>queryString</literal>.</para>
|
||||
<para>If for some reason, you need a more powerful matching strategy, you can use
|
||||
regular expressions. The strategy implementation is then
|
||||
<classname>RegexRequestMatcher</classname>. See the Javadoc for this class for more
|
||||
information.</para>
|
||||
<para>In practice we recommend that you use method security at your service layer, to
|
||||
control access to your application, and do not rely entirely on the use of security
|
||||
constraints defined at the web-application level. URLs change and it is difficult to
|
||||
take account of all the possible URLs that an application might support and how
|
||||
requests might be manipulated. You should try and restrict yourself to using a few
|
||||
simple ant paths which are simple to understand. Always try to use a
|
||||
<quote>deny-by-default</quote> approach where you have a catch-all wildcard
|
||||
(<literal>/**</literal>) defined last and denying access.</para>
|
||||
<para>Security defined at the service layer is much more robust and harder to bypass, so
|
||||
you should always take advantage of Spring Security's method security
|
||||
options.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Use with other Filter-Based Frameworks</title>
|
||||
<para>If you're using some other framework that is also filter-based, then you need to
|
||||
|
Loading…
x
Reference in New Issue
Block a user