14

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

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

4

5 回答 5

31

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

所以。

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

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

除非。

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

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

然后您可以使用C Sharp 编译器将该代理类转换为库 (.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;

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

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

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

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

于 2009-05-22T13:20:03.307 回答
4

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

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

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

于 2009-05-20T13:26:09.207 回答
1

垫,

我也有这样的问题,我有办法避免使用 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");
于 2009-07-29T18:26:07.300 回答
1

感谢这个伟大的提示,快速浏览了你的东西,你有很多好主意。这是我要补充的一点——我正在弄清楚 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);
    });

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

于 2010-11-22T20:21:12.477 回答
1

由于我没有评论的声誉,我想提一下 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 服务器进行了测试。谢谢!

于 2011-01-24T19:27:39.093 回答