4

当我使用 SSL 和客户端证书从浏览器外 Silverlight 4 应用程序调用 IIS 7.5(在 Windows 7 64 位上)时,我遇到了一个问题,并显示消息“I/O 操作已由于线程退出或应用程序请求而中止。(0x800703e3)“。该请求确实到达了 IIS。这是来自失败请求跟踪的示例:

由于线程退出或应用程序请求,I/O 操作已中止。(0x800703e3) http://www.slipjig.org/IISError.gif

我正在使用浏览器 HTTP 堆栈,因为客户端 HTTP 堆栈不支持客户端证书。试图访问服务器的客户端代码是 Prism 模块加载器。如果我在浏览器外运行应用程序但忽略客户端证书,或者如果我在浏览器内运行应用程序但需要客户端证书,它工作正常。似乎是两者的结合导致了问题。

我尝试了以下方法来收集更多信息:

  • 使用 Fiddler 查看失败的请求。如果 Fiddler 正在运行,它就可以工作(大概是因为 Fiddler 处理客户端证书的方式不同?);
  • 创建了一个 .aspx Web 表单来提供模块 .xaps;
  • 创建了一个 HTTPModule 来查看我是否可以在请求失败之前拦截它;
  • 使用数据包嗅探器查看是否可以判断客户端证书是否正确发送。

除了我在跟踪文件中看到的信息之外,以上都没有给我提供太多有用的信息,尽管 Fiddler 的事情很有趣。

有任何想法吗?提前致谢!麦克风

4

3 回答 3

4

在这个问题上,我用头撞墙了好几个星期。这是我学到的东西以及我最终如何解决它。

Prism 的 FileDownloader 类使用 System.Net.WebClient 加载模块。在 OOB 模式下,WebClient 似乎使用与 IE 相同的堆栈,但它显然要么不发送客户端证书,要么(更有可能)没有与服务器正确协商 SSL/客户端证书握手。我这样说是因为:

  • 我能够使用 Firefox 和 Chrome 成功请求 .xap 文件;
  • 无法使用 IE 成功请求 .xap 文件;
  • IIS 将失败并返回 500,而不是 403。

我无法很好地了解电线上实际发生的事情。如果我使用 Fiddler,它会起作用,因为 Fiddler 会拦截与服务器的通信并自己处理客户端证书握手。由于 SSL,尝试使用数据包嗅探器显然不会告诉我任何事情。

所以 - 我首先在服务器端花了很多时间试图消除可能导致问题的东西(不需要的处理程序、模块、功能等)。

当这不起作用时,我尝试修改 Prism 源代码以使用浏览器的 HTTP 堆栈而不是 WebClient。为此,我创建了一个设计类似于 FileDownloader 的新类,实现了使用浏览器堆栈的 IFileDownloader。然后我对 XapModuleTypeLoader(它实例化下载器)进行了一些更改,以使其使用新类。这种方法因我最初遇到的相同错误而失败。

然后我开始研究是否可以使用商业的第三方 HTTP 堆栈。我找到了一个支持我需要的功能并且支持 Silverlight 4 运行时的软件。我创建了另一个使用该堆栈的 IFileDownloader 实现,并且 BOOM - 它起作用了。

这种方法的好消息是,我不仅可以使用它来加载模块,还可以使用它来保护客户端和我们的 REST API 之间的通信(我们之前打算放弃的好处)。

我计划向 Prism 提交一个补丁,以允许下载器在外部注册或绑定,因为它目前被硬编码为使用自己的 FileDownloader。如果有人对此感兴趣或对我正在使用的商业 HTTP 堆栈感兴趣,请联系我 (msimpson -at-abelsolutions -dot-com) 以获取链接和代码示例。

而且我必须说这一点 - 我仍然不确定根本问题是在客户端还是服务器端的 HTTP 堆栈中,但它仍然是 Microsoft 的失败。

于 2010-08-14T16:31:20.240 回答
0

我们(Slipjig 和我)本周发现似乎确实有解决这些问题的方法,或者至少,我们正在确定是否有可靠、可重复的方法。我们对此仍然不积极,但这是我们目前所知道的:

首先,如果您有这样的代码,您可以开始使用浏览器或客户端堆栈发出请求:

首先,在您的 Silverlight XAML 中放置一个“WebBrowser”控件,并使其向您的 HTTPS 站点发送请求。

这可能会为用户弹出证书对话框。大不了。接受。如果您只有一个证书,那么您可以关闭 IE 中的一个选项来禁止显示该消息。

private void Command_Click(object sender, RoutedEventArgs e) {
  // This does not pop up the cert dialog if the option to take the first is turned on in IE settings:
  BrowserInstance.Navigate(new Uri("https://www.SiteThatRequiresClientCertificates.com/"));
}

然后,在用户调用的单独处理程序中,创建堆栈的实例,客户端或浏览器:

private void CallServer_Click(object sender, RoutedEventArgs e) {
           // Works with BrowserHttp factory also:
            var req = WebRequestCreator.ClientHttp.Create(new Uri("https://www.SiteThatRequiresClientCertificates.com/"));
            req.Method = "GET";
            req.BeginGetResponse(new AsyncCallback(Callback), req);
}

最后,回调:

private void Callback(IAsyncResult result)
{
            var req = result.AsyncState as System.Net.WebRequest;
            var resp = req.EndGetResponse(result);
            var content = string.Empty;
            using (var reader = new StreamReader(resp.GetResponseStream())) {
                content = reader.ReadToEnd();
            }
            System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                Results.Text = content;
            });
}
于 2010-12-08T00:45:38.987 回答
0

我有同样的问题,我通过使用 makecert 创建证书来修复它。按照本文http://www.codeproject.com/Articles/24027/SSL-with-Self-hosted-WCF-Service中的步骤操作,并将 CN 替换为您的 ip/域。就我而言,我已经在本地机器上测试了该服务并运行如下命令:

1) makecert -sv SignRoot.pvk -cy authority -r signroot.cer -a sha1 -n "CN=Dev Certification Authority" -ss my -sr localmachine

运行第一个命令后,将证书从“个人”目录拖到“受信任的根证书颁发机构”

2) makecert -iv SignRoot.pvk -ic signroot.cer -cy end -pe -n CN="localhost" -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localmachine -sky exchange -sp "Microsoft RSA SChannel 加密提供程序”-sy 12

如果您想在另一台机器上运行 silverlight 应用程序,请导出在步骤 1 中创建的证书,然后将其导入您希望运行应用程序的任何机器上。

于 2012-08-13T11:29:18.200 回答