问题
According to our provider we need to send this kind of Header:
<soapenv:Header>
<wsse:Security 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>string</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">string</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
But when checking out with Fiddler I sent this header:
<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/HuqG5V/ExLj3CNfRenvjEAAAAA7YcLXCnGukqViuu2jfqDDp47VC4vVV1Omqf/X2lHIcsACQAA</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-5d0431d0-d951-4a22-91c1-a33d76ce41b3-1">
<o:Username>username</o:Username>
<o:Password>password</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
I'm using a custom Binding as follows (I used it on another webservice with the same authetication method and works ok)
private static Binding CreateMultiFactorAuthenticationBinding()
{
HttpsTransportBindingElement httpTransport = new HttpsTransportBindingElement();
httpTransport.MaxReceivedMessageSize = int.MaxValue;
//AddressHeader addressHeader = AddressHeader.CreateAddressHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", security, xmlObjectSerializer);
CustomBinding binding = new CustomBinding();
binding.Name = "myCustomBinding";
TransportSecurityBindingElement messageSecurity = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement();
messageSecurity.IncludeTimestamp = false;
messageSecurity.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
messageSecurity.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
messageSecurity.SetKeyDerivation(false);
TextMessageEncodingBindingElement Quota = new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8);
Quota.ReaderQuotas.MaxDepth = 32;
Quota.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
Quota.ReaderQuotas.MaxArrayLength = 16384;
Quota.ReaderQuotas.MaxBytesPerRead = 4096;
Quota.ReaderQuotas.MaxNameTableCharCount = 16384;
binding.Elements.Add(Quota);
binding.Elements.Add(messageSecurity);
binding.Elements.Add(httpTransport);
return binding;
}
private WaybillManagementPOD GetClient()
{
CustomBinding customBinding = (CustomBinding)CreateMultiFactorAuthenticationBinding();
EndpointAddress endpointAddress = new EndpointAddress(this.EndPointAddr);
WaybillManagementPOD proxy = ChannelFactory<WaybillManagementPOD>.CreateChannel(customBinding, endpointAddress);
ServicePointManager.ServerCertificateValidationCallback = (obj, certificate, chain, errors) => true;
ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3;
ChannelFactory _bankChannel = new ChannelFactory<WaybillManagementPOD>(customBinding, this.EndPointAddr);
ChannelFactory<WaybillManagementPOD> channelFactory = null;
WaybillManagementPOD client = null;
channelFactory = new ChannelFactory<WaybillManagementPOD>(customBinding, endpointAddress);
channelFactory.Credentials.UserName.UserName = this.WsUser;
channelFactory.Credentials.UserName.Password = this.WsPass;
client = channelFactory.CreateChannel();
return client;
}
public registrarCartaDePorteResponse registrarCP(ParametrosRegistro reg)
{
WaybillManagementPOD cliente = GetClient();
try
{
registrarCartaDePorte req = new registrarCartaDePorte(reg);
registrarCartaDePorteResponse resp = cliente.registrarCartaDePorte(req);
return resp;
}
catch (Exception e)
{
throw e;
}
}
PS: I know it's not of good practice to bypass SSL certificate, but right now is for testing only.
Neither my provider nor I cannot figure out where is the error coming from, or where the error lies, if it's in the type of binding or something else.
回答1:
I finally used as suggested here Correct way communicate WSSE Usernametoken for SOAP webservice
<endpoint ...>
<headers>
<wsse:UsernameToken xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' >
<wsse:Username>Bob</wsse:Username>
<wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>
1234
</wsse:Password>
</wsse:UsernameToken>
</headers>
</endpoint>
</client>
Also now I call the webservice directly from the class created by the WCF reference, instead of using the custom class above.
Plus copying the information from the service solution to the UI solution, see here: WCF Error - Could not find default endpoint element that references contract 'UserService.UserService'
Now everything seems working fine.
来源:https://stackoverflow.com/questions/25059931/wcf-client-security-header-error-an-invalid-security-token-was-provided