实现一个通过SSL使用Web服务的C#客户端?

实现一个通过SSL使用Web服务的C#客户端?,c#,visual-studio,web-services,ssl,console-application,C#,Visual Studio,Web Services,Ssl,Console Application,因此,我将ServiceReference添加到一个C#控制台应用程序中,该应用程序调用从Oracle公开的Web服务 我已经做好了所有的设置,当它不使用SSL(http)时,它可以像桃子一样工作。我现在正试图使用SSL进行设置,但在将其添加到服务引用(甚至Web引用)时遇到了问题。例如,当我尝试将其添加到VisualStudio中时,服务公开的URL(https)没有返回适当的web方法 基础连接已关闭:发送时发生意外错误。 从传输流接收到意外的EOF或0字节。 元数据包含无法解析的引用:“”

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

我已经做好了所有的设置,当它不使用SSL(http)时,它可以像桃子一样工作。我现在正试图使用SSL进行设置,但在将其添加到服务引用(甚至Web引用)时遇到了问题。例如,当我尝试将其添加到VisualStudio中时,服务公开的URL(https)没有返回适当的web方法

基础连接已关闭:发送时发生意外错误。 从传输流接收到意外的EOF或0字节。 元数据包含无法解析的引用:“”

我遇到的另一个难题是关于证书管理和部署。我有大约1000个外部客户端站点需要使用这个小实用程序,它们需要在适当的证书存储中安装证书才能连接到Web服务。不确定处理此问题的最佳方法。它们需要在根存储中吗

我花了好几个小时在网上浏览各种选项,但在任何地方都找不到一个清晰的答案

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

1) 有人有一些关于在VisualStudio中设置使用SSL的Web服务的好链接吗

2) 我应该如何注册证书?它应该存在于哪个商店?我可以使用CertMgr之类的工具来注册它吗


一定会有一本好书/教程/任何东西向我展示关于设置这样的东西的常见良好实践。我就是找不到它

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

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


如果客户机是外部的,那么您必须让公开服务的人员从著名的CA(如Verisign、Thawte、,GeoTrust等,或者作为安装包的一部分,将公共证书安装到每台机器上机器级别的受信任根证书颁发机构中。这会有问题,例如无法撤销证书,但会删除提示。

我已经解决了这个问题。我花了比我想谈论的时间长得多的时间,但我想分享我的解决方案,因为看到标准让我非常恼火。“哦,我修好了!谢谢!”帖子让每个人都在关注到底发生了什么

所以

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

在VisualStudio2008中使用“添加服务引用…”时,服务点管理器的名称应为SSL3

除非

您获取一个静态WSDL文档,然后单击

然后可以使用将该代理类转换为库(.dll),并将其添加到.Net项目的“引用”中

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

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

// We're using SSL here and not TLS. Without this line, nothing workie.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
好吧,我对自己印象很深,因为在我的开发盒上测试非常棒。然后我部署到另一个客户端,由于权限/权限问题,它无法再次连接。这闻起来像是证书(不管它们闻起来像什么)。要解决此问题,我需要将站点的证书注册到本地计算机上的受信任根

certmgr -add -c "c:\someDir\yourCert.cer" -s -r localMachine root
这允许我将证书分发到我们的客户端站点,并为用户自动安装它。我仍然不确定不同版本的windows在自动证书注册方面会有多“安全友好”,但到目前为止它工作得很好

希望这个答案能帮助一些人。也感谢blowdart在这一点上提供的所有帮助,并提供了一些见解。

Mat

我也有这样的问题,我有办法避免使用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");

谢谢你的建议,快速浏览一下你的资料,你有很多好主意。下面是我要补充的一点——我正在研究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 { }
    }
  }
}

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

因为我没有评论的名声,我想提到Mat Nadrofsky的答案和强制SSL3的代码示例也是类似于

进行此操作时出错 HTTP请求到。 这可能是因为 未配置服务器证书 在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服务器进行测试。谢谢

您是否与创建网站的人员进行了检查,以了解他们的网站是如何配置的?他们在同一个构建中
/// <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);
    });
// We're using SSL here and not TLS. Without this line, nothing workie.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;