HttpFirewall普通模式
HttpFirewall 普通模式就是使用 DefaultHttpFirewall,该类的校验规则就要简单很多,我们来看一下其 getFirewalledRequest 方法:
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
FirewalledRequest fwr = new RequestWrapper(request);
if (!isNormalized(fwr.getServletPath()) || !isNormalized(fwr.getPathInfo())) {
throw new RequestRejectedException("Un-normalized paths are not supported: " + fwr.getServletPath()
+ (fwr.getPathInfo() != null ? fwr.getPathInfo() : ""));
}
String requestURI = fwr.getRequestURI();
if (containsInvalidUrlEncodedSlash(requestURI)) {
throw new RequestRejectedException("The requestURI cannot contain encoded slash. Got " + requestURI);
}
return fwr;
}
可以看到,首先构建了 RequestWrapper 对象对原始请求中的功能进行了增强。在 RequestWrapper 构建的过程中,主要做了两件事:
-
将请求地址中//格式化为/。
-
将请求中 servletPath 和 pathInfo 中用分号隔开的参数提取出来,只保留路径即可。
举个简单例子,例如你的请求地址是 http://localhost:8080//get ,假设 contextPath 为空,那么在原始请求中获取到的 servletPath 是 //get,而在 fwr 对象中获取到的 servletPath 则是 /get。
需要注意的是,Tomcat 容器本身会自动将 // 转为 /,而 Jetty 和 Undertow 则不会;这三个容器默认都会自动将用分号隔开的参数剔除,只保留请求路径。
获取到 fwr 对象之后,接下来调用 isNormalized 方法判断 servletPath 和pathInfo 是否规范, 判断逻辑和 StrictHttpFirewall 中的逻辑一致,这里不再赘述。
containsInvalidUrlEncodedSlash 用来判断 requestURI 中是否包含编码后的斜杠,即 %2f 或者 %2F,默认不允许包含此字符。如果开发者有需求,可以通过 setAllowUrlEncodedSlash 方法设置允许 %2f 或者 %2F 存在。
一般来说,并不建议开发者在项目中使用 DefaultHttpFirewall,因为相比于 StrictHttpFirewall,DefaultHttpFirewall 的安全性要差很多。如果开发者一定要使用,只需要提供一个 DefaultHttpFirewall 的实例即可:
@Bean
HttpFirewall httpFirewall() {
return new DefaultHttpFirewall();
}