Dot-Net

如何添加 SOAP 安全標頭

  • August 24, 2020

我已經閱讀了很多文章和答案,但我無法解決。

我在我的項目中使用 .NET Framework 4.0。因此,我首先將 WebService 添加為服務引用並在我的 app.config 上獲取綁定。我將列出我的嘗試


嘗試#1

我像這樣實例化了服務並添加了憑據:

在 App.Config 上

<binding name="SubscriptionWSImplServiceSoapBinding" >
 <security mode="TransportWithMessageCredential">
   <transport clientCredentialType="Basic"/>
 </security>
</binding>

SubscriptionWSImplServiceClient ClientWs = new SubscriptionWSImplServiceClient();
ClientWs.ClientCredentials.UserName.UserName = "some-username";
ClientWs.ClientCredentials.UserName.Password = "some-password";

var SomeResposne = ClientWs.RunMethod(); //I have exception at this point

我得到一個異常如下:

System.ArgumentException: The provided URI scheme 'http' is invalid;
expected 'https'. Parameter name: via at System.ServiceModel.Channels

例外情況是 Web 服務的 url 必須是 HTTPS,但給我的 Web 服務 url 是 HTTP 而不是 HTTPS。

但我不介意 HttpS 並進行了第二次嘗試。


嘗試#2

this answer所述, 我嘗試如下:

BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
CustomBinding customBinding = new CustomBinding(binding);
SecurityBindingElement element = customBinding.Elements.Find<SecurityBindingElement>();
element.IncludeTimestamp = false;

EndpointAddress address = new EndpointAddress("https://www.GivenServiceUrl.com/WebService"); //Note that the url does not end as ..svc or ..asmx! Just the name like this with no dot or extension


SubscriptionWSImplServiceClient ClientWs = new SubscriptionWSImplService(customBinding, address);
ClientWs.ClientCredentials.UserName.UserName = "some-username";
ClientWs.ClientCredentials.UserName.Password = "some-password";

var SomeResposne = ClientWs.RunMethod(); //I have exception at this point

我得到一個異常如下:

System.ServiceModel.Security.SecurityNegotiationException:無法為具有權限“ https://www.GivenServiceUrl.com/WebService ”的 SSL/TLS 安全通道建立信任關係

因此,我進行了第三次嘗試,我在我的項目中將參考作為 WebReference 而不是作為 ServiceReference。


嘗試#3

SubscriptionWSImplService ClientWs2 = new SubscriptionWSImplService();
var SomeResposne = ClientWs.RunMethod(); //I have exception at this point

我現在不知道如何發送安全標頭。

我得到一個異常如下:

System.Web.Services.Protocols.SoapHeaderException: An error was
discovered processing the <wsse: Security> header

但是在這裡,我無法添加必要的標題。你能幫我解決這個問題嗎?


Attempt 1 或 Attempt 2 或 Attempt 3,考慮到我使用的是 Framework 4.0,應該使用哪一個?我該如何解決這個問題?

根據文件,最終請求 SOAP 必須如下所示:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sub="http://subscription.services.ws.fourplay.com.tr/">
  <soapenv:Header>
     <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <wsse:UsernameToken wsu:Id="UsernameToken-12" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
           <wsse:Username>admin</wsse:Username>
           <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">123456</wsse:Password>
          <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">1lcj+WbCMlrPyhcud4QxiQ==</wsse:Nonce>
          <wsu:Created>2012-06-05T10:23:26.879Z</wsu:Created>
       </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body>
     <sub:RunMethod>
        <!--Optional:-->
        <sub:opaque id>555555555</sub:opaque id>
        <sub:params>
           <!--Optional:-->
           <name>GUID</name>
           <!--Optional:-->
           <value>2fc4ce1d-645e-41f4-811e-28510a02a17f </value>
        </sub:params>      
</sub: RunMethod >

我通過使用沒有聲明任何憑據的 WCF 解決了它。我通過建構我的自定義標題來做到這一點我從這個連結獲得了幫助

public class SoapSecurityHeader : MessageHeader
   {
       private readonly string _password, _username, _nonce;
       private readonly DateTime _createdDate;

       public SoapSecurityHeader(string id, string username, string password, string nonce)
       {
           _password = password;
           _username = username;
           _nonce = nonce;
           _createdDate = DateTime.Now;
           this.Id = id;
       }

       public string Id { get; set; }

       public override string Name
       {
           get { return "Security"; }
       }

       public override string Namespace
       {
           get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
       }

       protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
       {
           writer.WriteStartElement("wsse", Name, Namespace);
           writer.WriteXmlnsAttribute("wsse", Namespace);
       }

       protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
       {
           writer.WriteStartElement("wsse", "UsernameToken", Namespace);
           writer.WriteAttributeString("Id", "UsernameToken-10");
           writer.WriteAttributeString("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

           writer.WriteStartElement("wsse", "Username", Namespace);
           writer.WriteValue(_username);
           writer.WriteEndElement();

           writer.WriteStartElement("wsse", "Password", Namespace);
           writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
           writer.WriteValue(_password);
           writer.WriteEndElement();

           writer.WriteStartElement("wsse", "Nonce", Namespace);
           writer.WriteAttributeString("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
           writer.WriteValue(_nonce);
           writer.WriteEndElement();

           writer.WriteStartElement("wsse", "Created", Namespace);
           writer.WriteValue(_createdDate.ToString("YYYY-MM-DDThh:mm:ss"));
           writer.WriteEndElement();

           writer.WriteEndElement();
       }
   }

以及如何使用我從這個連結得到的標題。

引用自:https://stackoverflow.com/questions/19111773