Consuming a web service using digest authenticatio

2019-03-05 17:48发布

问题:

We are using C# to send XML data via SOAP. The service requires HttpDigest authentication with #PasswordDigest and #Base64Binary Nonce. Our binding code:

protected BasicHttpBinding binding = new BasicHttpBinding()
{
            Name = "ShipmentServiceSoapBinding",
            CloseTimeout = new TimeSpan(0, 01, 0),
            OpenTimeout = new TimeSpan(0, 01, 0),
            ReceiveTimeout = new TimeSpan(0, 10, 0),
            SendTimeout = new TimeSpan(0, 5, 0),
            AllowCookies = false,
            BypassProxyOnLocal = false, 
            HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
            MaxBufferPoolSize = 5242880,
            MaxReceivedMessageSize = 655360,
            MessageEncoding = WSMessageEncoding.Text ,
            TextEncoding =  new UTF8Encoding(),
            UseDefaultWebProxy = true,
            ReaderQuotas = new XmlDictionaryReaderQuotas() { MaxDepth = 32, MaxStringContentLength = 81920, MaxArrayLength = 1638400, MaxBytesPerRead = 409600, MaxNameTableCharCount = 163840 },
            Security = new BasicHttpSecurity() { Mode = BasicHttpSecurityMode.TransportWithMessageCredential, 
                                                 //Message = new BasicHttpMessageSecurity() { AlgorithmSuite = SecurityAlgorithmSuite.Default, ClientCredentialType = BasicHttpMessageCredentialType.UserName}, 
                                                 Transport = new HttpTransportSecurity(){ ClientCredentialType = HttpClientCredentialType.Digest}},

};

We are encountering 3 different problems based on what type of BasicHttpSecurityMode we are choosing.

  1. Transport - The XML does not include any security information
  2. TransportCredentialOnly - The error we get states that the endpoint cannot be https://
  3. TransportWithMessagecredential - This isn't using digest

Now their ServiceReference allows us to use ClientCredentials class, so here is how we tried using HttpDigest:

typeClient.ClientCredentials.HttpDigest.ClientCredential.UserName = "username";
typeClient.ClientCredentials.HttpDigest.ClientCredential.Password = "password";

I've read on other StackOverflow question that for digest we should be using SoapHeader with AuthHeader, but there is no way for us to match it with what they give is in the API. Is there any other way of doing it? Or is their API not written correctly for C#?

回答1:

It is much more complicated to use digest auth in this scenario - you will need to implement IClientMessageInspector to get it working... this enables you to modify the http headers in a way that is needed for digest auth.

Helpful links:

  • https://stackoverflow.com/a/3257760/847363
  • http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/
  • http://social.msdn.microsoft.com/Forums/en/wcf/thread/0f09954e-3cef-45b3-a00d-f0f579a06bf7
  • http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iclientmessageinspector.aspx
  • http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iclientmessageinspector.beforesendrequest.aspx
  • http://yuzhangqi.itpub.net/post/37475/500654
  • http://wcfpro.wordpress.com/category/wcf-extensions/
  • http://social.technet.microsoft.com/wiki/contents/articles/1322.how-to-inspect-wcf-message-headers-using-iclientmessageinspector-en-us.aspx
  • http://weblogs.asp.net/paolopia/archive/2007/08/23/writing-a-wcf-message-inspector.aspx
  • http://wcfpro.wordpress.com/2011/03/29/iclientmessageinspector/