实现使用SSL上的Web服务的C#客户端?

所以我已经将一个ServiceReference添加到C#控制台应用程序中,该应用程序调用从Oracle公开的Web服务。

我已经完成了所有设置,当它不使用SSL(http)时它就像桃子一样。 我现在正尝试使用SSL进行设置,并且我遇到了将其添加到服务引用(甚至Web引用)的问题。 例如,当我尝试将该服务添加到Visual Studio时,该服务所在的URL(https)未返回相应的Web方法。

底层连接已关闭:发送时发生意外错误。 从传输流中收到意外的EOF或0字节。 元数据包含无法解析的引用:’ https ://srs204.mywebsite.ca: 7776/ SomeDirectory/ MyWebService?WSDL ‘

我遇到的另一个窘境是证书管理和部署。 我有大约1000个外部客户端站点需要使用这个小实用程序,他们需要安装在相应的证书库中的证书才能连接到Web服务。 不确定处理此问题的最佳方法。 他们需要在根商店吗?

我花了几个小时在网上查看各种选项,但无法在任何地方得到一个干净的答案。

总而言之,我在这里有几个问题:

1)在Visual Studio中使用SSL设置Web服务的人有什么好的链接吗?

2)我应该如何注册证书? 它应该存在哪个商店? 我可以使用像CertMgr这样的东西进行注册吗?

必须有一本好的书/教程/任何能够向我展示设置此类内容的常见良好实践。 我似乎无法找到它!

好吧,我已经弄明白了。 我花了很长时间来讨论这个问题,但我想分享我的解决方案,因为看到标准是我的一个巨大的烦恼。 “哦,我修好了!谢谢!” 这些post让每个人都挂在实际发生的事情上。

所以。

根本问题是默认情况下Visual Studio 2008使用TLS进行SSL握手,而我尝试连接的基于Oracle / Java的Webservice使用SSL3。

在Visual Studio 2008中使用“添加服务引用…”时, 无法指定服务点管理器的安全协议应为SSL3。

除非。

您获取静态WSDL文档并使用wsdl.exe生成代理类 。

wsdl /l:CS /protocol:SOAP /namespace:MyNamespace MyWebService.wsdl 

然后,您可以使用C Sharp编译器将该代理类转换为库(.dll)并将其添加到.Net项目“References”中。

 csc /t:library /r:System.Web.Services.dll /r:System.Xml.dll MyWebService.cs 

此时,您还需要确保已在“引用”中包含System.Web.Services。

现在,您应该能够在代码中没有问题的情况下调用您的Web服务。 为了使其工作,您需要在实例化服务之前添加一行神奇的代码。

 // We're using SSL here and not TLS. Without this line, nothing workie. ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 

好吧,所以我对自己印象非常深刻,因为我的开发盒测试很棒。 然后我部署到另一个客户端框,由于权限/权限问题,它将无法再次连接。 这闻起来像我的证书(无论它们闻起来像什么)。 为解决此问题,我使用certmgr.exe将站点的证书注册到本地计算机上的受信任根。

 certmgr -add -c "c:\someDir\yourCert.cer" -s -r localMachine root 

这允许我将证书分发到我们的客户端站点并自动为用户安装。 我仍然不确定不同版本的Windows对于像这样的自动化证书注册的“安全友好”程度如何,但它到目前为止工作得很好。

希望这个答案可以帮助一些人。 感谢blowdart也为您提供了所有帮助,并提供了一些见解。

听起来好像Web服务正在使用自签名证书。 坦率地说,这不是最好的方法。

假设您是一个大型组织并且它是内部的,您可以设置自己的可信证书颁发机构,这对于Active Directory来说尤其容易。 从该CA,托管Oracle服务的服务器可以请求证书,您可以使用AD策略通过将其置于计算机存储的受信任根目录中来信任内部CA的根证书。 这将消除手动信任或接受Web服务上的证书的需要。

如果客户端计算机是外部的,那么您将不得不让公开服务的人员从Verisign,Thawte,GeoTrust等众所周知的CA之一购买“真实”证书,或者作为安装捆绑包的一部分公共证书并将其安装到每台计算机上的计算机级别的受信任的根证书颁发机构中。 这有问题,例如无法撤销证书,但会删除提示。

感谢这个伟大的提示,快速浏览一下你的东西,你有很多好主意。 这是我的一点点补充 – 我正在弄清楚webMethods和(惊喜!)它与你连接的Oracle应用服务器(SSL3而不是TLS)有同样的问题。 你的方法很有效,这是我的附录。

给定静态类“Factory”,提供这两个方便的花花公子:

 ///  /// Used when dispatching code from the Factory (for example, SSL3 calls) ///  /// Make this guy have values for debugging support public delegate void CodeDispatcher(ref string flag); ///  /// Run code in SSL3 -- this is not thread safe. All connections executed while this /// context is active are set with this flag. Need to research how to avoid this... ///  /// Debugging context on exception /// Dispatching code public static void DispatchInSsl3(ref string flag, CodeDispatcher dispatcher) { var resetServicePoint = false; var origSecurityProtocol = System.Net.ServicePointManager.SecurityProtocol; try { System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3; resetServicePoint = true; dispatcher(ref flag); } finally { if (resetServicePoint) { try { System.Net.ServicePointManager.SecurityProtocol = origSecurityProtocol; } catch { } } } } 

然后消耗这些东西(你毫无疑问已经猜到了,但无论如何都要在这里放一个鼓):

  var readings = new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading[] { new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() { attrID = 1, created = DateTime.Now.AddDays(-1), reading = 17.34, userID = 2 }, new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() { attrID = 2, created = DateTime.Now.AddDays(-2), reading = 99.76, userID = 3 }, new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() { attrID = 3, created = DateTime.Now.AddDays(-5), reading = 82.17, userID = 4 } }; ArchG2.Portal.Utils.wmArchG201.Factory.DispatchInSsl3(ref flag, (ref string flag_inner) => { // creates the binding, endpoint, etc. programatically to avoid mucking with // SharePoint web.config. var wsFireWmdReading = ArchG2.Portal.Utils.wmArchG201.Factory.Get_fireWmdReading(ref flag_inner, LH, Context); wsFireWmdReading.fireWmdReading(readings); }); 

这就是诀窍 – 当我得到更多时间时,我将解决线程问题(或不解决)。

由于我没有评论的声誉,我想提一下,Mat Nadrofsky的答案和强制SSL3的代码示例也是类似于错误的解决方案

将HTTP请求发送到https:// xxxx / whatever时发生错误。 这可能是由于在HTTPS情况下使用HTTP.SYS未正确配置服务器证书。 这也可能是由客户端和服务器之间的安全绑定不匹配引起的。

只是用

 // We're using SSL here and not TLS. Without this line, nothing workie. ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 

如Mat所述。 使用HTTPS中的SAP NetWeaver PI Server进行测试。 谢谢!

垫,

我也有这样的问题,我有办法避免使用certmgr.exe将证书添加到远程计算机上的受信任root。

 X509Store store; store = new X509Store("ROOT", StoreLocation.LocalMachine); store.Open(OpenFlags.ReadWrite); store.Add(certificate); 

可以像这样创建“证书对象”:

 X509Certificate2 certificate = new X509Certificate2("Give certificate location path here");