2017-10-16 21 views
0

Je suis en train d'installer un service WCF avec l'authentification basée sur les certificats, suivant ce guide: https://msdn.microsoft.com/en-au/library/ff648360.aspx?f=255&MSPPError=-2147217396service WCF avec l'authentification par certificat: « L'appelant n'a pas été authentifié par le service »

J'ai suivi toutes les étapes (je crois), en résumé, sont:
1) a généré un certificat CA auto-signé et installé comme une machine de niveau de confiance CA:

enter image description here

2) généré un certificat pour le service (signé par le certificat CA, CN=QvxServiceCert) et installé au niveau de la machine:

enter image description here

3) configuré le comportement de point de terminaison de service WCF pour utiliser le certificat. Ma configuration de service ressemble à ceci:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> 
    </startup> 

    <system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="wsHttpEndpointBinding"> 
      <security> 
      <message clientCredentialType="Certificate" /> 
      </security> 
     </binding> 
     </wsHttpBinding> 
    </bindings> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="QvxServiceBehavior"> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
      <serviceCredentials> 
      <serviceCertificate findValue="CN=QvxServiceCert" /> 
      </serviceCredentials> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <services> 
     <service name="esqQvxScheduler.Service.QvxSchedulerAPI" behaviorConfiguration="QvxServiceBehavior"> 
     <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" 
      name="wsHttpEndpoint" bindingName="" contract="esqQvxScheduler.Service.IQvxSchedulerAPI" /> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:8733/QvxSchedulerAPI/" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
    </system.serviceModel> 
</configuration> 

4) a généré un certificat pour le client (encore une fois, signé par le certificat CA, celui-ci a CN=QvxClientCert) et installé au niveau de l'utilisateur:

enter image description here

5) configuré le comportement du client WCF pour l'utiliser pour l'authentification. Ceci est ma config client:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> 
    </startup> 
    <system.serviceModel> 
     <behaviors> 
      <endpointBehaviors> 
       <behavior name="qvxClientBehavior"> 
        <clientCredentials> 
         <clientCertificate findValue="CN=QvxClientCert" /> 
        </clientCredentials> 
       </behavior> 
      </endpointBehaviors> 
     </behaviors> 
     <bindings> 
      <wsHttpBinding> 
       <binding name="wsHttpEndpoint"> 
        <security> 
         <message clientCredentialType="Certificate" /> 
        </security> 
       </binding> 
      </wsHttpBinding> 
     </bindings> 
     <client> 
      <endpoint address="http://localhost:8733/QvxSchedulerAPI/" binding="wsHttpBinding" behaviorConfiguration="qvxClientBehavior" 
       bindingConfiguration="wsHttpEndpoint" contract="QvxSchedulerAPI.IQvxSchedulerAPI" 
       name="wsHttpEndpoint"> 
       <identity> 
        <certificate encodedValue="[A LONG AUTOGENERATED STRING THE MEANING OF WHICH I HAVE NO IDEA]" /> 
       </identity> 
      </endpoint> 
     </client> 
    </system.serviceModel> 
</configuration> 

6) Gave l'utilisateur qui exécute l'accès client au certificat, en émettant ce qui suit sur la ligne de commande: cacls "C:\Users\MyUsername\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-742627442-1779984360-2302642487-1000" /E /G "MyUser-PC\MyUsername":R

Cela a été fait suivant le guide, sans n'importe quel problème que je pourrais voir. Tout semble ok ... mais lorsque je tente d'appeler le service de mon client, tout ce que j'obtenir cette exception frustrante vague et inutile:

Unhandled Exception: System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service. ---> System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed. 
    at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target) 
    at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState) 
    --- End of inner exception stack trace --- 

Server stack trace: 
    at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout) 
    at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnOpen(TimeSpan timeout) 
    at System.ServiceModel.Security.TlsnegoTokenProvider.OnOpen(TimeSpan timeout) 
    at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) 
    at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 
    at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout) 
    at System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(TimeSpan timeout) 
    at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) 
    at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 
    at System.ServiceModel.Channels.SecurityChannelFactory`1.ClientSecurityChannel`1.OnOpen(TimeSpan timeout) 
    at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 
    at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout) 
    at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout) 
    at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout) 
    at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout) 
    at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 
    at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout) 
    at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 
    at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout) 
    at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade) 
    at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) 
    at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) 
    at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) 

Répondre

0

Eh bien, après beaucoup d'essais et d'erreurs, se avère que vous soit doivent avoir une liste de révocation installé pour votre CA ou vous devez spécifier explicitement que vous ne voulez pas un chèque de révocation, en ajoutant ceci à la balise de votre comportement ClientCredentials:

<serviceCertificate> 
    <authentication revocationMode="NoCheck"/> 
</serviceCertificate> 

et vice-versa pour le côté service:

<clientCertificate> 
    <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck"/> 
</clientCertificate> 

En outre, vous devez supprimer l'étiquette de certificat autogénérée dans le client et la remplacer par une instruction pour rechercher le certificat:

<identity> 
    <certificateReference findValue="CN=QvxServiceCert" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" /> 
</identity>