【问题标题】:HttpWebRequest vs Fiddler using SSL使用 SSL 的 HttpWebRequest 与 Fiddler
【发布时间】:2014-08-07 23:39:49
【问题描述】:

我有一个使用 HttpWebRequest 将一些数据发送到第三方服务的网络应用程序。当我通过网络代码运行它时它失败了,但是当我使用 Fiddler 的作曲家发送几乎完全相同的数据时它可以工作。

我说“差不多”是因为数据包含密码摘要、随机数和时间戳,每条消息都会发生变化。我已经设置了一个断点并获取了网络应用程序即将发送的数据并将其粘贴到 Fiddler 中,它可以工作。

我也设置了我的代码以通过 Fiddler 的代理运行,这很棒 - 我可以看到正在发送的“原始”数据 - 它仍然失败,但它使我能够检查标题是否完全相同并且把他们弄得乱七八糟(没有发现任何有用的东西)。

    WebProxy myproxy = new WebProxy("127.0.0.1:8889", false);
    req.Proxy = myproxy;

我已禁用 Fiddler 的“自动身份验证”和“跟随重定向”选项(保留在“修复内容长度标头”上),以防其中一个导致 Fiddler 变得聪明。

这篇文章是一个 https URL,所以我必须添加以下几行来在解密 HTTPS 流量时忽略 Fiddler 的证书问题

    ServicePointManager
        .ServerCertificateValidationCallback +=
        (sender, cert, chain, sslPolicyErrors) => true;

有谁知道我应该启用或禁用 HttpWebRequest 上的任何选项以使其像 Fiddler 一样?由于实际内容似乎相同,因此安全/身份验证选项可能有所不同?

更改 Fiddler 的“解密 HTTPS”设置似乎没有任何影响,只是意味着我无法查看数据。

是否可以选择使用 HttpWebRequest 以外的方法?还有哪些不只是在后台使用 HttpWebRequest 的库?我不需要异步,但 HttpClient 是否使用更新的库来更好地处理事情?

我看过其他关于连接和提高 HttpWebRequest 性能的帖子,但目前我只是发布一条消息。

如果有帮助的话,标题如下所示:

POST https://www.server.com/enterprise/soap?ServiceName=PassportService&auth=1 HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: http://www.server.com/ws/passport/2008/04/PassportService#publishDocumentWithParameters
Host: vha.server.com
Content-Length: 4601
Expect: 100-continue
Connection: Keep-Alive

消息的主体只是 SOAP xml

以下是实现.NET Network Tracing的一些数据

System.Net Information: 0 : [8864] ConnectStream#7307007 - Sending headers
{
Content-Type: text/xml; charset=utf-8
SOAPAction: http://www.server.com/ws/passport/2008/04/PassportService#publishDocumentWithParameters
Host: vha.server.com
Content-Length: 4393
Expect: 100-continue
Connection: Keep-Alive
}.
System.Net Information: 0 : [8864] SecureChannel#63848051::.ctor(hostname=vha.server.com, #clientCertificates=0, encryptionPolicy=RequireEncryption)
System.Net Information: 0 : [8864] Enumerating security packages:
System.Net Information: 0 : [8864]     Negotiate
System.Net Information: 0 : [8864]     NegoExtender
System.Net Information: 0 : [8864]     Kerberos
System.Net Information: 0 : [8864]     NTLM
System.Net Information: 0 : [8864]     Schannel
System.Net Information: 0 : [8864]     Microsoft Unified Security Protocol Provider
System.Net Information: 0 : [8864]     WDigest
System.Net Information: 0 : [8864]     TSSSP
System.Net Information: 0 : [8864]     pku2u
System.Net Information: 0 : [8864]     CREDSSP
System.Net Information: 0 : [8864] SecureChannel#63848051 - Left with 0 client certificates to choose from.
System.Net Information: 0 : [8864] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent  = Outbound, scc     = System.Net.SecureCredential)
System.Net Information: 0 : [8864] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = (null), targetName = vha.server.com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [8864] InitializeSecurityContext(In-Buffer length=0, Out-Buffer length=112, returned code=ContinueNeeded).
System.Net.Sockets Verbose: 0 : [8864] Socket#55285825::Send()

...然后有一些证书来回...

System.Net Information: 0 : [8864] SecureChannel#63848051 - Remote certificate was verified as valid by the user.
System.Net Information: 0 : [8864] ProcessAuthentication(Protocol=Tls, Cipher=Rc4 128 bit strength, Hash=Md5 128 bit strength, Key Exchange=RsaKeyX 2048 bit strength).
System.Net.Sockets Verbose: 0 : [8864] Socket#55285825::Send()

...然后还有一些东西...

System.Net Verbose: 0 : [8864] Exiting HttpWebRequest#49916336::GetRequestStream()  -> ConnectStream#7307007
System.Net Verbose: 0 : [8864] ConnectStream#7307007::Write()
System.Net Verbose: 0 : [8864] Data from ConnectStream#7307007::Write
System.Net Verbose: 0 : [8864] 00000000 : 3C 73 6F 61 70 65 6E 76-3A 45 6E 76 65 6C 6F 70 : <soapenv:Envelop

... 更多 SOAP 数据随之而来(看起来像加密版本... ...加密回复回来了,然后它被解密了...

System.Net Information: 0 : [8864] Connection#4562529 - Received status line: Version=1.1, StatusCode=401, StatusDescription=Unauthorized.
System.Net Information: 0 : [8864] Connection#4562529 - Received headers
{
Vary: Accept-Encoding
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Length: 666
Content-Type: text/xml;charset=UTF-8
Date: Thu, 07 Aug 2014 06:21:40 GMT
Server: XXXX Web Server 8
}.
System.Net Information: 0 : [8864] ConnectStream#27021036::ConnectStream(Buffered 666 bytes.)
System.Net Information: 0 : [8864] Associating HttpWebRequest#49916336 with ConnectStream#27021036
System.Net Information: 0 : [8864] Associating HttpWebRequest#49916336 with HttpWebResponse#16709290

...带有一些带有错误信息的 XML(第 3 方似乎无法用来查明问题...

【问题讨论】:

  • “当我通过网络代码运行它时失败”是什么意思?它是如何失败的?你有没有使用 Fiddler 的“比较”功能来验证这两个请求是否相同?如果您在请求上禁用 ExpectContinue,会有变化吗?
  • 感谢@Eric,“失败”意味着由于某种原因第三方服务器不喜欢它并返回“401 未授权”响应。是的,我已经比较了这两个请求,除了安全细节之外它们是相同的(显然响应不同)。如果我删除“期望:100-继续”标题它仍然有效,“连接:保持活动”似乎也没有必要。
  • 第 3 方维护了一个允许 IP 地址的白名单,每种方法显示的原始 IP 地址是否可能存在差异?即 Fiddler 只是显示为我的公共 IP(这是允许的)但不知何故(这对我来说听起来很疯狂)HttpWebRequest 正在做一些奇怪的事情,看起来请求来自我的内部 192.168.1.1 IP 地址? IPv6 会导致问题吗?
  • "401 Unauthorized" 提示输入凭据; 403 是它不喜欢您的凭据。在 Fiddler 案例中,您有 401 吗?如果一个请求通过 IPv6 而另一个通过 IPv4,那么是的,这可能会有所不同。在 Fiddler 中,右键单击会话并选择属性。有没有提到“DNSFailover”?你能收集 Wireshark/NetMon 的捕获吗?
  • 我怀疑他们可能没有严格实现 HTTP 代码。如果我两次重播相同的数据(虽然在 nonce 数据上失败),我可以让 Fiddler 作曲家生成 401 错误。如果数据不好,或者我还没有弄清楚的其他事情不好,他们会发回 401。不,没有提到 DNSFailover。是的,我可以在 Wireshark 中收集信息,但我没有服务器私钥来解密它。我可以在 Wireshark 中看到两者都使用 IP4。

标签: c# ssl httpwebrequest fiddler


【解决方案1】:

简短的回答是没有区别。

感谢@EricLaw 的帮助,我能够排除他能想到的任何其他变量。

问题出在密码摘要中的时间戳。我的机器时间略有偏差,而他们的时间也是如此(但反过来)。所以结果是当我将数据粘贴到 Fiddler 时它起作用了,因为我稍微延迟了它(但不是太多)。这些请求有一个 37 秒的窗口,当它从代码运行时,它看起来像是从未来到他们的服务器的时间。

当只有一个变量时,这可能就是问题所在!

感谢您的耐心和帮助埃里克。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多