【问题标题】:intercepting http file upload using TCP/IP使用 TCP/IP 拦截 http 文件上传
【发布时间】:2011-02-13 05:07:07
【问题描述】:

我已经编写了一个代理来拦截我的 tomcat 的 http 请求。

每个请求都会通过我的代理并在到达 tomcat 服务器之前进行一些检查。我是通过使用 java 编写的 TCP/IP 绑定端口来实现的。

除了文件上传(多部分 POST 表单)提交之外,所有请求(GET 和 POST)都能够成功路由到 tomcat 服务器。

即使我能够获取 TCP/IP 中的所有字节并且能够将数据刷新回 tomcat 服务器,但数据会以某种方式被截断/丢失

在处理文件流内容时我需要做一些特殊的事情,比如编码等吗??

下面是我的示例代码...

protected void processData(InputStream input, OutputStream output) throws IOException { // reads a line of text from an InputStream StringBuffer data = new StringBuffer(""); StringBuffer data2 = new StringBuffer(""); StringBuffer data3 = new StringBuffer(""); StringBuffer data4 = new StringBuffer(""); int c; try { while ((c = input.read()) >= 0) { data.append((char) c); // check for an end-of-line character if ((c == 0) || (c == 10) || (c == 13)) { output.write(data.toString().getBytes(), 0, data.length()); data4.append(data.toString()); data = new StringBuffer(); count = 0; } else { if (count > 6) { if (input.available() == 1) { data.append((char) input.read()); } data2.append(data.toString()); data4.append(data.toString()); output.write(data.toString().getBytes(), 0, data .toString().length()); data = new StringBuffer(); } else { if (count == 6) { if (data.toString().toLowerCase() .indexOf("get /") == 0 || data.toString().toLowerCase() .indexOf("post /") == 0) { count = 0; contentLength = -1; // continue read data(header info) while ((line = readLine(input, data)) != null) { data = new StringBuffer(); // do my own stuff here dealing with headers if (StringUtils.isBlank(line)) { data4.append(line); output.write(line.getBytes(), 0, line.length()); break; } line += "\r\n"; output.write(line.getBytes(), 0, line.length()); data4.append(line); output.flush(); } } else { if (input.available() == 1) { data.append((char) input.read()); } } } else { if (input.available() == 1) { data.append((char) input.read()); output.write(data.toString().getBytes(), 0, data.toString().length()); data4.append(data.toString()); data3.append(data.toString()); data = new StringBuffer(); } } } count++; } if (processbody) total++; if (contentLength > 0 && contentLength == total) { log.debug("post data2: " + (data2.toString() != null ? data2.toString() : " ")); log.debug("post data3: " + (data3.toString() != null ? data3.toString() : " ")); log.debug("post data4: " + (data4.toString() != null ? data4.toString() : " ")); output.flush(); } } } catch (Exception e) { log.error("Error ", e); } finally { } }

【问题讨论】:

  • 仅当您使用InputStream/OutputStream 时,编码不是问题(因此 Reader/Writer)。至于具体问题,如果您更新问题以包含(重新)产生问题的最小可能代码 sn-p 以及实际输入和输出字节的真实示例,将会有所帮助。
  • 为什么不通过过滤器来实现呢?
  • @Alexey Sviridov servlet 过滤器有一些限制,例如如果您想在请求完全接收之前丢弃请求(例如,在受到攻击的情况下),您不能使用 servlet 过滤器来完成。你需要在它到达tomcat之前提供一些机制。

标签: java proxy tcp inputstream fileinputstream


【解决方案1】:

你的代码有一些缺陷:

  1. 您从InputStream 读取每个byte,然后将其转换为char 并将其附加到字符串生成器。如果流是编码字符,例如中文、希腊文、任何特殊字符,这将无法将流正确解码为可读字符串。或者,如果流是纯二进制或 ascii,则字符串不是存储流的最佳选择。当您提交文件多部分请求时,这很容易发生。

  2. 我不是并发方面的专家(所以我在这里可能会说无意义)但是如果同时有多个连接会发生什么。你应该小心这个。

据我所知,您想要处理 http 请求的标头,因此您没有理由不按照 Alexey Sviridov 的建议使用 servlet 过滤器。您可以实现自己的过滤器来拦截标头并对其进行处理。使用过滤器的好处是您可以让 servlet API 为您解析请求的标头,您无需担心何时读取/写入输入/输出流。

但是,如果您打算拦截请求的标头并决定是否应该将请求传递到您的 tomcat 或 servlet 容器,或者做任何不在 servlet 能力范围内的事情,您应该查看 http 代理图书馆。这是一个例子:

http://proxies.xhaus.com/java/

之前有一个关于writting HTTP Proxy in Java 堆栈溢出的问题。

很遗憾,我不想鼓励您编写自己的 http 代理。您需要考虑的问题太多了。

【讨论】:

  • 非常感谢您的回复。是的,你是对的。问题是因为将字节转换为 char。我已将代码更改为仅读取字节并将字节转换为标题部分的字符。其余的我只是读写。
【解决方案2】:

你这样做很艰难。只需读取字节并将它们写入另一端。您不关心字符串或字符串缓冲区或行终止字符。

【讨论】:

    猜你喜欢
    • 2018-05-04
    • 1970-01-01
    • 2011-10-09
    • 2023-03-21
    • 2018-07-08
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多