WCF客户端安全标头错误"提供了无效的安全令牌"

时间:2014-07-31 13:19:47

标签: c# wcf wcf-security

根据我们的提供商,我们需要发送这种标题:

<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>

但在与Fiddler结账时,我发送了这个标题:

<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>

我正在使用自定义绑定,如下所示(我在另一个使用相同认证方法的Web服务上使用它并且正常工作)

 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:我知道绕过SSL证书并不是一个好习惯,但现在仅用于测试。

我的提供者和我都无法弄清楚错误来自哪里,或者错误在哪里,如果它是绑定类型或其他类型。

1 个答案:

答案 0 :(得分:2)

我最终按照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> 

现在我直接从WCF引用创建的类调用webservice,而不是使用上面的自定义类。

另外将服务解决方案中的信息复制到UI解决方案,请参阅此处:WCF Error - Could not find default endpoint element that references contract 'UserService.UserService'

现在一切似乎都很好。