【问题标题】:Implement a C# Client that uses WebServices over SSL?实现一个通过 SSL 使用 WebServices 的 C# 客户端?
【发布时间】:2010-10-25 15:07:57
【问题描述】:

所以我已将 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 之类的东西来注册它吗?

必须有一本好书/教程/任何可以向我展示设置此类内容的常见良好做法的东西。就是找不到!

【问题讨论】:

  • 您是否与创建该网站的人核对以了解其最终配置方式?
  • 他们现在在同一栋楼里,所以如果是服务器相关的东西,我可以改变它。我可以在浏览器中调出 https URL,它会显示标准的 Oracle Web 服务测试页面。这样我就可以打了。当我点击该 URL 时,它确实要求我接受证书。我收到了两个需要注册的 .cer 文件(一个用于开发服务器,一个用于生产服务器)。
  • 如果您在浏览器中打开 url (https),​​您会看到预期的结果吗?其他人是否通过 https 使用此服务没有问题?我不确定 oracle Web 服务是如何工作的,但如果它托管在 IIS 上或通过 IIS 托管,则需要将域名 (webservice.servicehost.com) 添加为 SSL 主机标头。
  • 我是目前唯一一个尝试使用它的人。当我打开它时,我得到一个作为服务端点的页面。它有一些选项,我可以用来对其进行测试、运行压力测试、查看 WSDL 等。所以我很确定它可以正常运行,或者至少在外观上看起来是这样。我在没有 SSL 的 (http) 版本上获得了相同的页面,并且该版本运行良好。
  • 好吧,我正在继续我自己的研究。到目前为止,此链接已有所帮助...weblogs.asp.net/jan/archive/2003/12/04/41154.aspx

标签: c# visual-studio web-services ssl console-application


【解决方案1】:

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

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

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

【讨论】:

  • 感谢您的回复!我已经获得了两个证书。一个用于“开发”服务器,另一个用于“生产”服务器。我们的客户站点是外部的,所以我不得不担心手动注册证书。有关将它们放入受信任的根机器存储的最佳方法的任何好的链接?生产证书来自 GTE Cyber​​Trust,是涵盖所有发行策略和所有应用策略的 Global Root 证书。
  • 所以你不需要担心实时服务器,它会开箱即用,因为 GTE 是一个受信任的根(我认为你有点困惑 - 它不太可能是实时服务器有它自己的根证书,它可能只是一个普通的证书)。为了检查,我会添加对实时服务的引用,看看会发生什么。如果这一切都很好,那么对于开发人员来说,您只需要在您的机器上安装证书。启动 MMC 并添加证书管理单元,告诉它使用本地机器。然后将开发证书导入受信任的根目录。
  • 明白了。我已经运行了 MMC,使用证书管理单元确保开发证书颁发机构已添加到本地计算机的“受信任的根”中。仍然无法连接到服务的开发版本。我实际上无法针对生产版本进行测试,因为我们还没有结束开发。不过,我也许可以让他们尝试为我设置一些东西。开发证书是否有可能出现问题?如果我的系统上安装了正确的证书,我应该能够添加 HTTPS 服务引用而不会出错,对吧?
  • 我应该澄清“他们的结局”的错误,我的意思是我为开发服务器获得的证书并不是该服务器上实际使用的证书。
  • Naw,他们的结尾有什么问题值得怀疑;) 所以,在 IE 中浏览到他们的端点。越过证书警告,单击挂锁图标并从那里安装
【解决方案2】:

嗯,我已经想通了。我花了比我想谈论的时间更长的时间,但我想分享我的解决方案,因为看到标准是我的一个巨大的烦恼。 “哦,我修好了!谢谢!”让每个人都对实际发生的事情感到困惑的帖子。

所以。

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

当您在 Visual Studio 2008 中使用“添加服务引用...”时,您有 no way to specify that the security protocol 服务点管理器应该是 SSL3。

除非。

您获取一个静态 WSDL 文档和use wsdl.exe to generate a proxy class

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

然后您可以使用C Sharp Compiler 将该代理类转换为库 (.dll) 并将其添加到您的 .Net 项目“参考”中。

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;

好的,我对自己印象深刻,因为在我的开发盒上进行的测试非常棒。然后我部署到另一个客户端盒子,由于权限/权限问题它不会再次连接。对我来说,这闻起来像证书(不管它们闻起来像什么)。为了解决这个问题,我used certmgr.exe 将该站点的证书注册到本地计算机上的受信任根。

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

这允许我将证书分发到我们的客户站点并为用户自动安装它。我仍然不确定不同版本的 windows 对像这样的自动证书注册有多“安全友好”,但到目前为止效果很好。

希望这个答案可以帮助一些人。也感谢吹镖在这方面的所有帮助并提供了一些见解。

【讨论】:

  • 如果您想出问题,请始终回答您自己的问题。先生,您救了我。 (我有一个支持 TLS 的网络服务器广告。发现它不支持!)
  • 我只是在浏览 SO。对此没有真正的疑问,但很高兴看到您的解决方案。这听起来像是花了很多研究。很好的解释!谢谢!
  • 很高兴听到我帮助了某人并希望能减轻一点痛苦! :)
【解决方案3】:

垫子,

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

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

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

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

【讨论】:

  • 您好,感谢您的回复!我们已经使用使用 certmgr.exe 的自定义脚本部署到我们的客户站点,但我更喜欢这个解决方案。下次有更改时,我们会在深入研究该代码时试一试。
【解决方案4】:

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

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

/// <summary>
/// Used when dispatching code from the Factory (for example, SSL3 calls)
/// </summary>
/// <param name="flag">Make this guy have values for debugging support</param>
public delegate void CodeDispatcher(ref string flag);

/// <summary>
/// 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...
/// </summary>
/// <param name="flag">Debugging context on exception</param>
/// <param name="dispatcher">Dispatching code</param>
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);
    });

这就是诀窍——当我有更多时间时,我会解决线程问题(或不解决)。

【讨论】:

  • +1 - 太棒了。有时很难找到这些类型的模糊错误和修复。感谢您的发布和荣誉!
【解决方案5】:

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

的错误的解决方案

制作时发生错误 对https://xxxx/whatever 的 HTTP 请求。 这可能是因为 未配置服务器证书 在 HTTPS 中正确使用 HTTP.SYS 案子。这也可能是由 安全绑定不匹配 在客户端和服务器之间。

随便用

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

正如马特所说。在 HTTPS 中使用 SAP NetWeaver PI 服务器进行了测试。谢谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-04
    • 2017-09-15
    • 1970-01-01
    • 2018-03-02
    • 2011-04-28
    • 2010-10-26
    • 2010-10-17
    • 1970-01-01
    相关资源
    最近更新 更多