c# - 通过 "Service Reference"连接到 SSL SOAP 主机并传递安全 header

标签 c# ssl credentials service-reference

我正在尝试使用服务引用通过 C# 连接到 SSL SOAP 服务主机。 这是我的请求消息:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <s:Header>
        <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo/zwMmtdsVhFsAVDkQbiV/4AAAAA1zXtnc72UEm+4tlKzvCxsvN6OC2prvRIljIX4XzHKEYACQAA</VsDebuggerCausalityData>
        <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <u:Timestamp u:Id="_0">
                <u:Created>2016-03-18T12:45:27.558Z</u:Created>
                <u:Expires>2016-03-18T12:50:27.558Z</u:Expires>
            </u:Timestamp>
            <o:UsernameToken u:Id="uuid-2c7986ba-eee5-4411-90a9-a02b625c55ff-1">
                <o:Username>MyUserName</o:Username>
                <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MyPlainPassword</o:Password>
            </o:UsernameToken>
        </o:Security>
    </s:Header>
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <generateId xmlns="http://com.vedaadvantage/dp3/Enterprise/StandardTradeCreditCommercial/IndividualCommercialService"/>
    </s:Body>
</s:Envelope>

这是我的服务发送给主机的消息。但是主机返回如下:

安全处理器无法在邮件中找到安全 header 。这可能是因为消息是不安全的错误,或者是因为通信双方之间的绑定(bind)不匹配。如果为安全配置了服务并且客户端未使用安全性,则可能会发生这种情况。

这是我的配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <system.serviceModel>

    <bindings>
      <customBinding>
        <binding name="myBinding">
          <textMessageEncoding messageVersion="Soap11" />
          <security  authenticationMode="UserNameOverTransport"
                     messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10" >
          </security>

          <httpsTransport />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="https://{URL}"
        binding="customBinding"
                bindingConfiguration="myBinding"
        contract="ServiceReference2.MyService"
                name="IndividualCommercialService" />
    </client>
  </system.serviceModel>
</configuration>

虽然当我通过 SOAPUI 或其他 HTTP Post 方法发送相同的 XML 时它工作正常。

我还提取并附加了证书和用户/通行证,如下所示:

private static X509Certificate2 DownloadSslCertificate(string strDNSEntry)
        {

            X509Certificate2 cert = null;
            using (TcpClient client = new TcpClient())
            {
                //ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;           
                client.Connect(strDNSEntry, 443);

                SslStream ssl = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                try
                {
                    ssl.AuthenticateAsClient(strDNSEntry);
                }
                catch (AuthenticationException e)
                {
                    //log.Debug(e.Message);
                    ssl.Close();
                    client.Close();
                    return cert;
                }
                catch (Exception e)
                {
                    //log.Debug(e.Message);
                    ssl.Close();
                    client.Close();
                    return cert;
                }
                cert = new X509Certificate2(ssl.RemoteCertificate);
                ssl.Close();
                client.Close();
                return cert;
            }
        }

        private static void Main(string[] args){
                var proxy = new MyService();

                var uri = proxy.Endpoint.Address.Uri;
                var cer = DownloadSslCertificate(uri.DnsSafeHost);

                EndpointIdentity identity = EndpointIdentity.CreateDnsIdentity(cer.Subject.Replace("CN=", ""));
                EndpointAddress address = new EndpointAddress(proxy.Endpoint.Address.Uri, identity);

                proxy.Endpoint.Address = address;

                proxy.ClientCredentials.UserName.UserName = "MyUserName";
                proxy.ClientCredentials.UserName.Password = "MyPlainPassword";
                proxy.ClientCredentials.ServiceCertificate.DefaultCertificate = cer;

                proxy.HellowWorld();
          }

我不确定我获取证书的方法是否正确,也不确定为什么 HTTP Post 有效但我的服务引用调用无效。

预先感谢您的帮助。

干杯

最佳答案

尝试查看 WSDL(服务引用)以查看隐藏文件,首先在解决方案资源管理器中选择显示所有文件。 您将在服务引用 Reference.svcmap -> Reference.cs 中看到,并在此文件中添加 ProtectionLevel = System.Net.Security.ProtectionLevel.Sign 如下图

[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.your.url/Service/", ConfigurationName = "Service.Service", ProtectionLevel = System.Net.Security.ProtectionLevel.Sign)]

应该对你有帮助。通常修改自动生成的代理是一个非常糟糕的主意,但似乎这是唯一的选择。

关于c# - 通过 "Service Reference"连接到 SSL SOAP 主机并传递安全 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36085231/

相关文章:

c# - 如何创建指向另一个 Action C# 的 Action?

c# - 继承时缺少方法异常

c# - 如何在 Xamarin.Forms 中使用 ReactiveUI 只执行一次命令?

python - 如何更好地存储我的服务器凭据以用于 Python 部署脚本?

Paypal 新沙箱帐户未生成 api 凭据

android - 使用 Android 的 Web 服务进行身份验证的正确方法

c# - 如何加快 Visual Studio 构建以匹配 MSBuild 并行性能?

security - 什么时候应该启用 HSTS?

Jquery ajax 加载停止从 https 站点工作

asp.net - 启用 SSL 时将 login.aspx 放在哪里