如何添加SOAP Security标头

E-A*_*E-A 6 .net soap web-services credentials

我已经阅读了很多文章和答案,但我无法解决这个问题.

我在我的项目中使用.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
Run Code Online (Sandbox Code Playgroud)

我得到一个例外如下:

 System.ArgumentException: The provided URI scheme 'http' is invalid;
 expected 'https'. Parameter name: via at System.ServiceModel.Channels
Run Code Online (Sandbox Code Playgroud)

例外情况说Web服务的url必须是HTTPS,但给定的Web服务URL是HTTP而不是HTTPS.

但我不介意HttpS并且进行了第二次尝试.


尝试#2

正如在这个答案中所说, 我尝试如下:

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
Run Code Online (Sandbox Code Playgroud)

我得到一个例外如下:

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
Run Code Online (Sandbox Code Playgroud)

我不知道如何发送安全头.

我得到一个例外如下:

 System.Web.Services.Protocols.SoapHeaderException: An error was
 discovered processing the <wsse: Security> header
Run Code Online (Sandbox Code Playgroud)

但在这里,我无法添加必要的标题.你能帮帮我吗?


尝试1或尝试2或尝试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 >
Run Code Online (Sandbox Code Playgroud)

E-A*_*E-A 5

我通过使用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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

以及如何使用标题我从这个链接得到它.

  • 不要使用"添加Web引用".这是传统的"ASMX"技术,不应该用于新的开发. (2认同)