提交 b595dc1d 编写于 作者: R Rossen Stoyanchev

Add advice on Spring MVC path matching for 5.3+

Closes gh-26750
上级 86123de8
......@@ -573,6 +573,56 @@ initialization parameters (`init-param` elements) to the Servlet declaration in
[[mvc-handlermapping-path]]
=== Path Matching
The Servlet API exposes the full request path as `requestURI` and further sub-divides it
into `contextPath`, `servletPath`, and `pathInfo` whose values vary depending on how a
Servlet is mapped. From these inputs, Spring MVC needs to determine the lookup path to
use for handler mapping, which is the path within the mapping of the `DispatcherServlet`
itself, excluding the `contextPath` and any `servletMapping` prefix, if present.
The `servletPath` and `pathInfo` are decoded and that makes them impossible to compare
directly to the full `requestURI` in order to derive the lookupPath and that makes it
necessary to decode the `requestUri`. However this introduces its own issues because the
path may contain encoded reserved characters such as `"/"` or `";"` that can in turn
alter the structure of the path after they are decoded which can also lead to security
issues. In addition, Servlet containers may normalize the `servletPath` to varying
degrees which makes it further impossible to perform `startsWith` comparisons against
the `requestUri`.
This is why it is best to avoid reliance on the `servletPath` which comes with the
prefix-based `servletPath` mapping type. If the `DispatcherServlet` is mapped as the
default Servlet with `"/"` or otherwise without a prefix with `"/*"` and the Servlet
container is 4.0+ then Spring MVC is able to detect the Servlet mapping type and avoid
use of the `servletPath` and `pathInfo` altogether. On a 3.1 Servlet container,
assuming the same Servlet mapping types, the equivalent can be achieved by providing
a `UrlPathHelper` with `alwaysUseFullPath=true` via <<mvc-config-path-matching>> in
the MVC config.
Fortunately the default Servlet mapping `"/"` is a good choice. However, there is still
an issue in that the `requestUri` needs to be decoded to make it possible to compare to
controller mappings. This is again undesirable because of the potential to decode
reserved characters that alter the path structure. If such characters are not expected,
then you can reject them (like the Spring Security HTTP firewall), or you can configure
`UrlPathHelper` with `urlDecode=false` but controller mappings will need to match to the
encoded path which may not always work well. Furthermore, sometimes the
`DispatcherServlet` needs to share the URL space with another Servlet and may need to
be mapped by prefix.
The above issues can be addressed more comprehensively by switching from `PathMatcher` to
the parsed `PathPattern` available in 5.3 or higher, see
<<mvc-ann-requestmapping-pattern-comparison>>. Unlike `AntPathMatcher` which needs
either the lookup path decoded or the controller mapping encoded, a parsed `PathPattern`
matches to a parsed representation of the path called `RequestPath`, one path segment
at a time. This allows decoding and sanitizing path segment values individually without
the risk of altering the structure of the path. Parsed `PathPattern` also supports
the use of `servletPath` prefix mapping as long as the prefix is kept simple and does
not have any characters that need to be encoded.
[[mvc-handlermapping-interceptor]]
=== Interception
......@@ -1650,7 +1700,7 @@ configuration.
[.small]#<<web-reactive.adoc#webflux-ann-requestmapping-pattern-comparison, WebFlux>>#
When multiple patterns match a URL, the best match must be selected. This is done with
one of the following depending on whether parsed `PathPattern`'s are enabled for use or not:
one of the following depending on whether use of parsed `PathPattern` is enabled for use or not:
* {api-spring-framework}/web/util/pattern/PathPattern.html#SPECIFICITY_COMPARATOR[`PathPattern.SPECIFICITY_COMPARATOR`]
* {api-spring-framework}/util/AntPathMatcher.html#getPatternComparator-java.lang.String-[`AntPathMatcher.getPatternComparator(String path)`]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册