Silverlight 4 OOB +浏览器HTTP堆栈+客户端证书=失败?

时间:2010-07-08 04:20:59

标签: silverlight iis certificate out-of-browser

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

The I/O operation has been aborted because of either a thread exit or an application request. (0x800703e3) http://www.slipjig.org/IISError.gif

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

我尝试了以下内容来收集更多信息:

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

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

有什么想法吗?提前致谢! 迈克

4 个答案:

答案 0 :(得分: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之间的通信(我们之前将放弃的好处)。< / p>

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

我必须这样说 - 我仍然不确定根问题是在客户端或服务器端的HTTP堆栈中,但它仍然是微软的失败。

答案 1 :(得分: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;
            });
}

答案 2 :(得分:0)

事实上,问题的解决方案可能就像这里的解决方案一样简单: http://forums.silverlight.net/forums/p/196906/458328.aspx

唯一需要的是将证书放在受信任的根存储中。但不幸的是,这在我的案例中并不起作用,我仍然在努力解决这个问题。

答案 3 :(得分:0)

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

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中创建的证书,然后将其导入到您希望运行应用程序的任何计算机上。