Dot-Net
如何添加 SOAP 安全標頭
我已經閱讀了很多文章和答案,但我無法解決。
我在我的項目中使用 .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(); } }以及如何使用我從這個連結得到的標題。