9

我的应用程序需要检查 POST 请求的内容/数据/正文/有效负载而不更改后续 getParameter 调用的结果。

从 inputStream 中读取正文:

可以使用 InputStream fromrequest.getInputStream或 BufferedReader from读取正文request.getReader

读取 POST 参数:

POST 请求通常在请求正文中包含请求参数。这些可以使用检索getParameter

问题:

第一次getParameter调用在内部解析 inputStream 并将所有参数插入到参数 HashMap 中。它要求 inputStream 仍然包含要解析的内容。因此,人们无法检查内容并且仍然可以进行有效的 getParameter 调用。

建议(但不充分)解决方案

创建一个请求包装器,用于缓存输入流并返回 getInputStream 的缓存。

我已经看到整个网络都建议了该解决方案,但它不起作用,因为getParameter实际上并没有调用getInputStream,而是指埋在请求对象中的原始 inputBuffer 。我已经尝试过了,无论是在 Servlet 内部还是使用过滤器

我能想到的唯一解决方案是重写 getParameter 以手动实际解析缓存的输入流。但这感觉是个坏主意。

有没有人有任何可行的替代方案?(这是Tomcat 5.5)这感觉应该是一个常见的用例;我不敢相信这有多么困难。

4

2 回答 2

1

正如@caskey 所建议的那样,一种可能的解决方案是使用反射将 inputBuffer 替换为可重放的输入缓冲区。但我没有使用这种方法,因为它感觉很顽皮。

相反,我在过滤器中创建了一个请求包装器,它将输入流读入一个字节数组并返回一个新InputStream的,它在内部使用ByteArrayInputStream该数组周围的所有getInputStream调用。

将输入流读取到字节数组后,我通过解析有效负载来创建参数映射。我合并了超类的参数映射以支持带有查询参数的 GET 案例。我已经覆盖了所有的 getParameter*() 方法来使用这个参数映射。

我曾经apache.axis.utils.IOUtils.readFully很容易将流读入字节数组。我目前正在使用javax.servlet.http.HttpUtils.parsePostData将数据解析为参数映射。HttpUtils.parsePostData实际上已弃用,所以当我找到它时,我可能会用更好的版本替换它。

但这有效,耶!

于 2013-09-03T07:41:24.113 回答
1

(那是一个相当老的tomcat,我假设升级到更现代的不是一种选择。)

您想要做的将需要拦截包装底层 InputStream 的具体 HttpServletResponse 对象的构造。将 InputStream 包装在一个推回输入流(或等效的)中是必要的。

Tomcat 5.5 太旧了,我什至无法想象如何“正常”完成,但也许您可以编写一个过滤器,使用反射来到达并交换具体请求对象内的 InputStream 对象。

于 2013-09-03T02:45:40.027 回答