【问题标题】:Log all network interactions of Java application记录 Java 应用程序的所有网络交互
【发布时间】:2013-09-01 23:31:10
【问题描述】:

我有一个巨大的 Java 应用程序(一个鲜为人知的应用服务器 GNUEnterprise 的客户端)及其源代码,我可以在对其进行一些更改后编译回来。该应用程序大量使用网络,我需要监控每个请求和响应。我可以使用像 Wireshark 这样的嗅探器,但该应用程序通过 SSL 与它的服务器一起工作,因此不知道 SSL 证书的私钥任何嗅探到的流量都是毫无用处的。

如何使每个请求和响应都从应用程序本身记录下来?我需要查看所有发送和接收的标头。我不想更改所有负责网络交互的代码。我想要的是放一个类似的代码

Network.setDefaultLogger(myCustomLoggerInstance);

在应用程序开始附近的某个地方,然后在 myCustomLoggerInstance 中执行我需要的所有日志记录。

此外,鉴于所有网络操作都是使用URLConnections 进行的,我可以使用con.getHeaderFields() 获取响应标头,并使用con.getRequestProperties() 获取请求标头。但是为什么没有cookies呢?如何以相同的方式转储发送和接收的 cookie?

编辑:我试图通过 SSL 模拟 RPC 应用程序与其服务器的通信,例如使用curl。为此,我需要获取应用程序网络流量的详细日志。

【问题讨论】:

  • 我会修改OpenJDK,实现提到的记录器功能,然后在库级别嗅探通信。
  • @auselen 太老套了。如果无法在应用程序级别执行此操作(看起来确实如此),我最好坚持使用外部日志记录代理服务器,就像 grayfairer 建议的那样。

标签: java debugging rpc


【解决方案1】:

记录所有 SSL 流量的快速方法是使用以下命令启动 java:

-Djavax.net.debug=all

或者将其设置为系统属性:

System.setProperty("javax.net.debug","all");

振作起来。如果你这样做,标准输出会很吵!

(*注意:仅记录 SSL 流量和 SSL 调试信息(握手等)。不记录常规套接字。)

【讨论】:

    【解决方案2】:

    你不能使用日志代理服务器吗? http://www.charlesproxy.com/ 还是 http://fiddler2.com/? Charles Proxy 还可以解码 AMF 请求,Fiddler 是 SSL 拦截的冠军。

    IIRC 您可以将系统属性 http.proxyHost 和 http.proxyPort 设置为 127.0.0.1 和 8888,java URLConnections 将通过您的日志代理服务器自动连接,您可以很好地查看 HTTP 流量。

    或者,如果打算能够重放通信,请使用 JMeter HTTP 代理,它以适合重放的格式记录。它还内置了对处理 cookie 的支持。

    如果应用程序使用了不错的 Web 服务,SoapUI 也有一个监视代理来拦截您已为其导入 WSDL 的 Web 服务调用。

    【讨论】:

    • 哦,它也有 SSL 流量嗅探。我一定会试试这个。
    • 要允许 SSL 嗅探,您还需要破解您的 java 信任库,请参阅:stackoverflow.com/questions/8549749/…
    • 我正在开发的应用程序已经处理了这个问题。它有一个利用HttpsURLConnection.setDefaultHostnameVerifier.setDefaultSSLSocketFactory 信任所有证书的类。如果没有建议的应用程序级解决方案,我会接受你的回答,因为它实际上做了我想要的,尽管方式不同。我还找到了一个免费的 Charles 替代品 webscarab,它在 Linux 上运行,不像 Fiddler。
    • 我坚持使用 Webscarab 代理。感谢您为我指明正确的方向!
    • 你让我去谷歌搜索“IIRC”,意思是“如果我没记错的话”
    【解决方案3】:

    我进一步挖掘,显然,HttpURLConnection 带有默认启用的 java.util.logging。

    查看相关问题: Java: Display request of an HttpURLConnection before sendingHow to enable wire logging for a java HttpURLConnection traffic?

    Java.util.logging 是 Sun 在 Java 1.4 中标准化日志提供程序的(失败的)尝试。如果您想避免调整系统属性,可以通过 jul-to-slf4j 模块将其桥接到 SLF4J。

    但我仍然更喜欢 Fiddler 或 JMeter 代理 :-)

    【讨论】:

    • 无法让它工作。现在我也更喜欢代理服务器。
    【解决方案4】:

    我只想发布一个可以在起点使用的代码的 sn-p。我没有“全局”记录器,但只需对现有代码进行少量更改,您就可以实现目标。我在标准输出上“记录”,因为您的问题可以分为两部分:从 UrlConnection 获取信息并将其存储以供进一步参考。

    此代码记录请求:

    public class URLConnectionReader {
    
      public static void main(String[] args) throws Exception {
      URL oracle = new URL("http://www.google.com/");
      URLConnection yc = oracle.openConnection();
    
      String headerName = null;
      for (int i = 1; (headerName = yc.getHeaderFieldKey(i)) != null; i++) {
        if (headerName.equals("Set-Cookie")) {
          String cookie = yc.getHeaderField(i);
          System.out.println("Cookie  ::  " + cookie);
        } else {
          System.out.println("Header: "+ yc.getHeaderField(i));
        }
      }
    
      BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
      String inputLine;
      while ((inputLine = in.readLine()) != null)
        System.out.println(inputLine);
      in.close();
    }
    

    }

    将所有这些数据保存到一个或多个文件中并不难。如果您认为我解决了您的问题,我很乐意根据需要使用其他详细信息编辑答案。

    【讨论】:

    • 谢谢,但它看起来像 getHeaderFieldKey(i)getHeaders() 出于某种原因跳过 Set-Cookie 标头。无论如何,我正在寻找一种为整个应用程序设置全局网络记录器的方法,而不必在任何发生网络交互的地方放置代码 sn-ps。此外,使用您的解决方案,我必须阅读连接两次。
    • 当然,将日志保存到文件也不是问题。所以我将我的问题分为以下两个部分:1)设置全局记录器; 2) 记录流量而不读取或发送响应和请求两次。
    • 糟糕,我的错。如果在URLConnection 实例上发送请求后调用getHeaders(),它不会第二次打开读取流,您实际上可以在那里看到Set-Cookie 标头。因此,为您 +1,对于所有错误的声明,我们深表歉意。剩下的是一种为所有网络连接设置代理的方法(我的意思是 OOP 模式代理,而不是代理服务器)。
    • 你为什么不简单地扩展 URLConnection 并覆盖 getConnection?将您的构造函数放入您的记录器实例。只是猜测。
    • @tapo:我正在寻找类似的东西,但如果我扩展URLConnection,我需要用我的CustomURLConnection 替换每个URLConnection 构造函数。如果我确定URLConnection 总是用构造函数实例化,这不会是一个大问题。但是可能有方法返回URLConnection 实例,例如URL.openConnection()。所以我也需要扩展和替换URL,也许还有别的东西。我不想把程序代码弄得乱七八糟,尤其是在它上面插入sn-ps。
    【解决方案5】:

    如果你想记录网络流量并且你有 URLConnection 对象,那么问题已经解决了!
    如果要在流级别记录,则需要在 I/O 流之上编写一个小包装器并在将所有数据传输到较低的网络层之前记录它们,否则您可以直接使用连接对象来获取所需的信息并记录它们.
    要管理 cookie,您应该使用 java 6 中引入的java.net.HttpCookie。您只需创建一个 CookieManager 实例并将其设置为默认 cookie 管理器:

    CookieManager cookieManager = new CookieManager();
    CookieHandler.setDefault(cookieManager);
    

    &你可以用它来管理连接cookies!

    【讨论】:

    • 最初我已经搜索了类似这个全局cookie管理器对象的东西,只针对所有网络操作,但后来我决定使用本地日志代理服务器就足够了。在这种情况下,我什至不需要干预源代码。顺便说一句,可以使用自定义 CookieManager 来记录传入和传出的请求标头,而不仅仅是 cookie。 CookieManager 的方法getputrequestHeadersresponseHeaders 相应地作为List<String> 类型的第二个参数。我想知道这些方法是在每次请求和响应时调用还是仅在使用 cookie 时调用。
    猜你喜欢
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多