【问题标题】:WCF client security header error "An invalid security token was provided"WCF 客户端安全标头错误“提供了无效的安全令牌”
【发布时间】:2014-09-23 11:00:56
【问题描述】:

根据我们的提供者,我们需要发送这种 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>

但是在使用 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 证书不是一个好习惯,但现在仅用于测试。

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

【问题讨论】:

    标签: c# wcf wcf-security


    【解决方案1】:

    我终于按照这里的建议使用了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 引用创建的类调用 web 服务,而不是使用上面的自定义类。

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

    现在一切似乎都正常了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-15
      • 1970-01-01
      • 2014-04-05
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      • 1970-01-01
      相关资源
      最近更新 更多