spring security RequestWrapper 源码
spring security RequestWrapper 代码
文件路径:/web/src/main/java/org/springframework/security/web/firewall/RequestWrapper.java
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.firewall;
import java.io.IOException;
import java.util.StringTokenizer;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
/**
* Request wrapper which ensures values of {@code servletPath} and {@code pathInfo} are
* returned which are suitable for pattern matching against. It strips out path parameters
* and extra consecutive '/' characters.
*
* <h3>Path Parameters</h3> Parameters (as defined in
* <a href="https://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>) are stripped from the path
* segments of the {@code servletPath} and {@code pathInfo} values of the request.
* <p>
* The parameter sequence is demarcated by a semi-colon, so each segment is checked for
* the occurrence of a ";" character and truncated at that point if it is present.
* <p>
* The behaviour differs between servlet containers in how they interpret the servlet
* spec, which does not clearly state what the behaviour should be. For consistency, we
* make sure they are always removed, to avoid the risk of URL matching rules being
* bypassed by the malicious addition of parameters to the path component.
*
* @author Luke Taylor
*/
final class RequestWrapper extends FirewalledRequest {
private final String strippedServletPath;
private final String strippedPathInfo;
private boolean stripPaths = true;
RequestWrapper(HttpServletRequest request) {
super(request);
this.strippedServletPath = strip(request.getServletPath());
String pathInfo = strip(request.getPathInfo());
if (pathInfo != null && pathInfo.length() == 0) {
pathInfo = null;
}
this.strippedPathInfo = pathInfo;
}
/**
* Removes path parameters from each path segment in the supplied path and truncates
* sequences of multiple '/' characters to a single '/'.
* @param path either the {@code servletPath} and {@code pathInfo} from the original
* request
* @return the supplied value, with path parameters removed and sequences of multiple
* '/' characters truncated, or null if the supplied path was null.
*/
private String strip(String path) {
if (path == null) {
return null;
}
int semicolonIndex = path.indexOf(';');
if (semicolonIndex < 0) {
int doubleSlashIndex = path.indexOf("//");
if (doubleSlashIndex < 0) {
// Most likely case, no parameters in any segment and no '//', so no
// stripping required
return path;
}
}
StringTokenizer tokenizer = new StringTokenizer(path, "/");
StringBuilder stripped = new StringBuilder(path.length());
if (path.charAt(0) == '/') {
stripped.append('/');
}
while (tokenizer.hasMoreTokens()) {
String segment = tokenizer.nextToken();
semicolonIndex = segment.indexOf(';');
if (semicolonIndex >= 0) {
segment = segment.substring(0, semicolonIndex);
}
stripped.append(segment).append('/');
}
// Remove the trailing slash if the original path didn't have one
if (path.charAt(path.length() - 1) != '/') {
stripped.deleteCharAt(stripped.length() - 1);
}
return stripped.toString();
}
@Override
public String getPathInfo() {
return this.stripPaths ? this.strippedPathInfo : super.getPathInfo();
}
@Override
public String getServletPath() {
return this.stripPaths ? this.strippedServletPath : super.getServletPath();
}
@Override
public RequestDispatcher getRequestDispatcher(String path) {
return this.stripPaths ? new FirewalledRequestAwareRequestDispatcher(path) : super.getRequestDispatcher(path);
}
@Override
public void reset() {
this.stripPaths = false;
}
/**
* Ensures {@link FirewalledRequest#reset()} is called prior to performing a forward.
* It then delegates work to the {@link RequestDispatcher} from the original
* {@link HttpServletRequest}.
*
* @author Rob Winch
*/
private class FirewalledRequestAwareRequestDispatcher implements RequestDispatcher {
private final String path;
/**
* @param path the {@code path} that will be used to obtain the delegate
* {@link RequestDispatcher} from the original {@link HttpServletRequest}.
*/
FirewalledRequestAwareRequestDispatcher(String path) {
this.path = path;
}
@Override
public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
reset();
getDelegateDispatcher().forward(request, response);
}
@Override
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException {
getDelegateDispatcher().include(request, response);
}
private RequestDispatcher getDelegateDispatcher() {
return RequestWrapper.super.getRequestDispatcher(this.path);
}
}
}
相关信息
相关文章
spring security CompositeRequestRejectedHandler 源码
spring security DefaultHttpFirewall 源码
spring security DefaultRequestRejectedHandler 源码
spring security FirewalledRequest 源码
spring security FirewalledResponse 源码
spring security HttpFirewall 源码
spring security HttpStatusRequestRejectedHandler 源码
spring security RequestRejectedException 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦