如何在java中使用fiddler捕获https

我正在Eclipse IDE中运行以下Java程序:

import java.net.*; import java.io.*; public class HH { public static void main(String[] args)throws Exception { //if i comment out the system properties, and don't set any jvm arguments, the program runs and prints out the html fine. System.setProperty("http.proxyHost", "localhost"); System.setProperty("http.proxyPort", "8888"); System.setProperty("https.proxyHost", "localhost"); System.setProperty("https.proxyPort", "8888"); URL x=new URL("https://www.google.com"); HttpURLConnection hc=(HttpURLConnection)x.openConnection(); hc.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2"); InputStream is=hc.getInputStream(); int u=0; byte[] kj=new byte[1024]; while((u=is.read(kj))!=-1) { System.out.write(kj,0,u); } is.close(); } } 

这会产生以下exception,如果fiddler处于RUNNING状态,则同时捕获和不捕获:

 Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown ... 

如果我closures小提琴手,程序运行良好,没有任何exception,产生的url我连接到的HTML。

或者,如果我指定System.setProperty("https.proxyPort", "443"); ,而不是: System.setProperty("https.proxyPort", "8888"); 它运行并打印出所有的html,即使在fiddler打开的情况下也没有例外,在捕捉模式下,但是依然没有从fiddler中捕捉。

然后,如果我通过eclipse的jvm参数设置这些系统属性,如: -DproxySet=true -DproxyHost=127.0.0.1 -DproxyPort=8888 ,同样的确切exception再次发生,只要fiddler应用程序正在运行,无论是在捕获和非捕获模式。 如果我closures小提琴手,程序将运行得很好。

如果我使用: System.setProperty("http.proxyHost", "127.0.0.1"); 而不是: System.setProperty("http.proxyHost", "localhost"); ,它运行良好与提琴应用程序运行,无论是捕捉/非捕捉模式,但也没有捕获stream量。

有人在那里,能够捕捉他们自己的httpsstream量与提琴手,而不是通过networking浏览器,但通过一个Java程序? 什么是jvm的论点,你如何设置它来做到这一点? 谢谢

创build一个包含Fiddler证书的密钥库。 将此密钥库用作JVM的信任库以及代理设置。

以下是如何做到这一点:

  • 导出Fiddler的根证书

工具 – >提琴手选项… – > HTTPS – >将根证书导出到桌面

  • 用这个证书创build一个密钥库

以pipe理员身份打开命令行(keytool不起作用)

<JDK_Home> \ bin \ keytool.exe -import -file C:\ Users \ <用户名> \ Desktop \ FiddlerRoot.cer -keystore FiddlerKeystore -alias Fiddler

提示时input密码。 这应该创build一个名为FiddlerKeystore的文件。

  • 现在以Fiddler作为代理,并将此密钥库作为信任库启动JVM。 你需要这些vmargs:

-DproxySet =真

-DproxyHost = 127.0.0.1

-DproxyPort = 8888

-Djavax.net.ssl.trustStore = <path\到\ FiddlerKeystore>

-Djavax.net.ssl.trustStorePassword = <密钥库密码>

在你的eclipse运行configuration中使用这些vmargs,你应该很好去。

我能够捕获从JVM制作的HTTPS请求,没有任何问题与此设置。

创build一个包含提琴手证书的密钥库并使用它:

 java -DproxySet=true -DproxyHost=127.0.0.1 -DproxyPort=8888 -Dhttps.proxyPort=8888 -Dhttps.proxyHost=127.0.0.1 -Djavax.net.ssl.trustStore=<path to FiddlerKeystore> -Djavax.net.ssl.trustStorePassword=<password> -jar test.jar 

如果您使用第三方HTTP库,则需要设置连接代理。 Apache Commons HttpClient示例:

 HttpClient httpClient = new HttpClient(); httpClient.getHostConfiguration().setProxy("localhost", 8888); 

我发现我还需要下面的java命令行选项

 -Dhttps.proxyPort=8888 -Dhttps.proxyHost=127.0.0.1 

您还可以将fiddler密钥导入到java可信证书存储区中:

  1. 导出Fiddler的根证书

    工具 – >提琴手选项… – > HTTPS – >动作 – >导出根证书到桌面

  2. 以admin身份运行:

“keytool.exe”-import -noprompt -trustcacerts -alias FiddlerRoot -file c:\ work \ FiddlerRoot.cer -keystore“C:\ Program Files \ Java \ jdk1.7.0_79 \ jre \ lib \ security \ cacerts”-storepass更改

另外我还遇到了一个问题,就是用Fiddler解密Google API客户端的httpsstream量。 问题是,默认情况下,它使用自己的证书存储:

 InputStream keyStoreStream = GoogleUtils.class.getResourceAsStream("google.jks"); SecurityUtils.loadKeyStore(certTrustStore, keyStoreStream, "notasecret"); 

这是我如何解决这个问题:

  HttpTransport transport = new NetHttpTransport() //istead of transport = GoogleNetHttpTransport.newTrustedTransport();