diff --git a/config/src/main/java/org/springframework/security/config/debug/DebugFilter.java b/config/src/main/java/org/springframework/security/config/debug/DebugFilter.java index 308719bcee..d5a17cbdd4 100644 --- a/config/src/main/java/org/springframework/security/config/debug/DebugFilter.java +++ b/config/src/main/java/org/springframework/security/config/debug/DebugFilter.java @@ -41,6 +41,8 @@ class DebugFilter extends OncePerRequestFilter { List 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); diff --git a/docs/manual/src/docbook/namespace-config.xml b/docs/manual/src/docbook/namespace-config.xml index dfe24b9fc5..ab4c93c775 100644 --- a/docs/manual/src/docbook/namespace-config.xml +++ b/docs/manual/src/docbook/namespace-config.xml @@ -142,17 +142,20 @@ <http> element is the parent for all web-related namespace functionality. The <intercept-url> element defines a pattern 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 - access 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 ROLE_ 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 + using an ant path style syntax + See the section on Request + Matching in the Web Application Infrastructure chapter for more details + on how matches are actually performed. + . You can also use regular-expression matching as an alternative (see the + namespace appendix for more details). The access 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 + ROLE_ 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 The interpretation of the comma-separated values in the access attribute depends on the implementation of the AccessDecisionManager which is used. In diff --git a/docs/manual/src/docbook/web-infrastructure.xml b/docs/manual/src/docbook/web-infrastructure.xml index fde7e0799b..f09cbae0f2 100644 --- a/docs/manual/src/docbook/web-infrastructure.xml +++ b/docs/manual/src/docbook/web-infrastructure.xml @@ -55,15 +55,16 @@
<classname>FilterChainProxy</classname> - 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 + Spring Security's web infrastructure should only be used by delegating to an + instance of FilterChainProxy. 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 DelegatingFilterProxy entry to web.xml - for each filter, making sure that they are ordered correctly. This is a cumbersome - approach and clutters up the web.xml file quickly if we have a - lot of filters. We would prefer to just add a single entry to - web.xml and deal entirely with the application context file for - managing our web security beans. This is where Spring Secuiryt's - FilterChainProxy 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 web.xml file quickly if you + have a lot of filters. FilterChainProxy lets us add a single + entry to web.xml and deal entirely with the application context + file for managing our web security beans. It is wired using a DelegatingFilterProxy, just like in the example above, but with the filter-name set to the bean name filterChainProxy. The filter chain is then declared in the @@ -89,8 +90,8 @@ context XML file in order to use this syntax. . It maps a particular URL pattern to a chain of filters built up from the bean names specified in the filters element. Both regular - expressions and Ant Paths are supported, and the most specific URIs appear first. At - runtime the FilterChainProxy will locate the first URI + expressions and Ant Paths are supported, and the most specific URLs appear first. At + runtime the FilterChainProxy will locate the first URL pattern that matches the current web request and the list of filter beans specified by the filters 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 @@ SecurityContextPersistenceFilter (with its default allowSessionCreation as true) would likely be sufficient. - In relation to lifecycle issues, the FilterChainProxy will - always delegate init(FilterConfig) and - destroy() methods through to the underlaying - Filters if such methods are called against - FilterChainProxy itself. In this case, - FilterChainProxy guarantees to only initialize and destroy - each Filter 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 targetFilterLifecycle initialization - parameter of DelegatingFilterProxy. By default this property is - false and servlet container lifecycle invocations are not - delegated through DelegatingFilterProxy. + Note that FilterChainProxy 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. When we looked at how to set up web security using namespace configuration, we used a DelegatingFilterProxy with the name @@ -126,15 +119,15 @@ namespace.
Bypassing the Filter Chain - As with the namespace, you can use the attribute filters = - "none" 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 SecurityContext contents during a - request, then it must have passed through the security filter chain. Otherwise - the SecurityContextHolder will not have been populated - and the contents will be null. + You can use the attribute filters = "none" 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 + SecurityContext contents during a request, then it must + have passed through the security filter chain. Otherwise the + SecurityContextHolder will not have been populated and + the contents will be null.
@@ -201,6 +194,78 @@
+
+ Request Matching and <interfacename>HttpFirewall</interfacename> + 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 FilterChainProxy decides which filter chain a + request should be passed through and also when the + FilterSecurityInterceptor 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. + The Servlet Specification defines several properties for the + HttpServletRequest which are accessible via getter + methods, and which we might want to match against. These are the + contextPath, servletPath, + pathInfo and queryString. Spring Security is + only interested in securing paths within the application, so the + contextPath is ignored. Unfortunately, the servlet spec does not + define exactly what the values of servletPath and + pathInfo will contain for a particular request URI. For example, + each path segment of a URL may contain parameters, as defined in RFC 2396 + You have probably seen this when a browser doesn't support cookies and the + jsessionid 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 + . The Specification does not clearly state whether these should be + included in the servletPath and pathInfo + 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. + The original values will be returned once the request leaves the + FilterChainProxy, so will still be available to the + application. + . Other variations in the incoming URL are also possible. For example, it + could contain path-traversal sequences (like /../) or multiple + forward slashes (//) 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, + FilterChainProxy uses an + HttpFirewall 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. + So, for example, an original request path + /secure;hack=1/somefile.html;hack=2 will be returned as + /secure/somefile.html. + . It is therefore essential that a + FilterChainProxy is used to manage the security filter chain. + Note that the servletPath and pathInfo 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. + 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 AntPathRequestMatcher which uses Spring's + AntPathMatcher to perform a case-insensitive match of the + pattern against the concatenated servletPath and + pathInfo, ignoring the queryString. + If for some reason, you need a more powerful matching strategy, you can use + regular expressions. The strategy implementation is then + RegexRequestMatcher. See the Javadoc for this class for more + information. + 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 + deny-by-default approach where you have a catch-all wildcard + (/**) defined last and denying access. + 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. +
Use with other Filter-Based Frameworks If you're using some other framework that is also filter-based, then you need to