问题
i need to consume WCF service over SSL while the request needs to be sign with one certificate and the response needs to be validated with another certificate.
i get this error while executing the code:
Cannot find a token authenticator for the 'System.IdentityModel.Tokens.X509SecurityToken' token type. Tokens of that type cannot be accepted according to current security settings.
according to WCF tracing it fails while trying to validate the response signature, because i can see the response from the server.
here's my WCF service settings:
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logKnownPii="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
<endToEndTracing propagateActivity="true" activityTracing="true"
messageFlowTracing="true" />
</diagnostics>
<behaviors>
<endpointBehaviors>
<behavior name="CHClientCertificateBehavior">
<clientCredentials supportInteractive="true">
<clientCertificate findValue="clientcert" storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
<serviceCertificate>
<defaultCertificate findValue="servercert" storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
<authentication certificateValidationMode="None" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="DPBasicHttpBindingWithSSL" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:02:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="2097152" maxBufferSize="524288" maxReceivedMessageSize="524288"
textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"
messageEncoding="Text">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
<customBinding>
<binding name="DPCustomHttpBindingWithSSL">
<security authenticationMode="CertificateOverTransport" allowSerializedSigningTokenOnReply="true" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireDerivedKeys="false"
securityHeaderLayout="Lax" />
<textMessageEncoding messageVersion="Soap11" />
<httpsTransport maxBufferPoolSize="2097152" maxBufferSize="524288" maxReceivedMessageSize="524288" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://myserver/service.asmx"
behaviorConfiguration="CHClientCertificateBehavior" binding="customBinding"
bindingConfiguration="DPCustomHttpBindingWithSSL" contract="ServiceRef.smssoap"
name="smsEndpoint">
<identity>
<certificateReference storeName="My" storeLocation="LocalMachine"
x509FindType="FindBySubjectName" findValue="myserver" />
</identity>
</endpoint>
</client>
</system.serviceModel>
as you can see, i tried both basicHttpBinding and customBinding (converted with the online tool http://webservices20.cloudapp.net/default.aspx), i tried to set different variations of settings combinations but still get this error.
any idea? canceling response certificate signing validation is also an option, but how do i set it??
回答1:
Try using the custom binding with the following configuration:
<security allowSerializedSigningTokenOnReply="true" />
回答2:
I had the same problem and posted a solution to it here (for those coming here looking for an answer):
WCF - Cannot find a token authenticator for X509SecurityToken
Based on the question, it appears to be the same solution:
- Change
authenticationMode="CertificateOverTransport"
toauthenticationMode="MutualCertificate"
- Use
MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10
- In the generated client, add
ProtectionLevel = ProtectionLevel.Sign
to theServiceContractAttribute
. This avoids having the body encrypted.
回答3:
SOLVED!
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="DPSSLXDIG">
<clientCredentials supportInteractive="false">
<clientCertificate findValue="clientcert" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
<serviceCertificate>
<defaultCertificate findValue="servercert" storeName="TrustedPeople" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
<authentication certificateValidationMode="None" revocationMode="NoCheck" />
</serviceCertificate>
<windows allowNtlm="false" allowedImpersonationLevel="None" />
<httpDigest impersonationLevel="None" />
<peer>
<peerAuthentication revocationMode="NoCheck" />
</peer>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="DPSSLXDIG">
<textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />
<security allowSerializedSigningTokenOnReply="true" authenticationMode="MutualCertificateDuplex"
requireDerivedKeys="false" securityHeaderLayout="Lax" messageProtectionOrder="SignBeforeEncrypt"
messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"
requireSecurityContextCancellation="false">
<secureConversationBootstrap />
</security>
<httpsTransport authenticationScheme="Anonymous" requireClientCertificate="true" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://myserver/webservice.asmx"
behaviorConfiguration="DPSSLXDIG" binding="customBinding"
bindingConfiguration="DPSSLXDIG" contract="serviceRef.smssoap"
name="smsEndpoint">
<identity>
<dns value="servercert" />
</identity>
</endpoint>
</client>
</system.serviceModel>
来源:https://stackoverflow.com/questions/21983634/wcf-error-cannot-find-a-token-authenticator