10 Stimmen

WCF-Dienstzertifikat und clientseitige Endpunktidentität - warum funktioniert es nicht?

[Update] - Ich hänge auch vollständige Konfigurationsdateien an, für Dienstleistung und für Kunde (außerhalb von hier, um das Thema nicht zu überschwemmen)

Die Situation, in der ich mich befinde, ist fast identisch mit der, die in este Frage, aber meine Frage ist etwas anders.

  • Ich verwende NetTcpBinding mit Sicherheit eingestellt auf TransportWithMessageCredential
  • Ich verwende Passwort/Benutzername Anmeldedaten, die von ASP.NET gesichert werden Anbieter
  • Mein Dienst wird selbst in Windows gehostet Dienst
  • I tun in meinem Endpunktverhalten haben spezifizierte Authentifizierung revocationMode="NoCheck"

Es ist erforderlich, dass der Dienst ein Zertifikat bereitstellt, um sich gegenüber Kunden zu authentifizieren. Das ist OK, ich tue es einfach:

<serviceCertificate findValue="***"
                    storeLocation="CurrentUser"
                    storeName="My"
                    x509FindType="FindByThumbprint"/>

Nun habe ich mir irgendwie vorgestellt, dass der Kunde am Ende

<identity>
  <certificate encodedValue="encoded certificate"/>
</identity>

Und er wird in der Lage sein, die Anmeldedaten des Dienstes zu überprüfen ohne dass das Zertifikat im Speicher auf dem Client-Rechner installiert ist .

Ich war überrascht zu lernen dass, obwohl ich die Dienstanmeldeinformationen auf Zertifikat eingestellt habe, WSDL stellt aus.

<Identity>
   <Dns>Foo</Dns>
</Identity>

Auch hier kann ich im Dienst die Identität auf CertificateReference setzen und sie mit demselben Zertifikat verknüpfen, und dann wird die WSDL die Identität als X509Certificate darstellen, aber wenn ich den Client ausführe, wird diese Einstellung ignoriert, und ich erhalte eine Fehlermeldung:

System.ServiceModel.Securi Das X.509-Zertifikat CN=xxx ist nicht im dem vertrauenswürdigen Personenspeicher. Das X.509 Zertifikat CN=xxx-Kettenbildung ist fehlgeschlagen. Das verwendete Zertifikat hat eine Vertrauenskette, die nicht verifiziert werden verifiziert werden kann. Ersetzen Sie das Zertifikat oder ändern Sie den certificateValidationMode. Eine Zertifikatskette wurde verarbeitet, aber endete in einem Root-Zertifikat, dem der Vertrauensanbieter nicht vertrauenswürdig ist.

Gibt es eine Möglichkeit, den Client dazu zu bringen, diesen Wert aus der Konfiguration zu verwenden und zu arbeiten, ohne ein Service-Zertifikat (oder dessen Root) auf dem Client-Rechner installieren zu müssen?

[UPDATE] Wenn Sie certificateValidationMode auf none setzen, verschwindet die Ausnahme zwar, aber aus Sicherheitsgründen ist dies eine inakzeptable Lösung.

Der Kunde muss lediglich bestätigen, dass er "irgendein" Zertifikat erhalten hat, ohne auf Einzelheiten einzugehen. Dadurch werden alle Arten von Man-in-the-Middle-Angriffen möglich. Die vom (angeblichen) Dienst gesendeten Informationen werden immer noch nicht mit dem in der Konfiguration hinterlegten Zertifikat abgeglichen.

4voto

Pedro Felix Punkte 1056

Lösungsskizze:

1) Definieren und registrieren Sie einen benutzerdefinierten X509CertificateValidator auf dem Kunden

2) In der Validieren Sie vergleichen Sie das angegebene Zertifikat mit dem Zertifikat, das sich in der EndpointAddress.Identity Eigentum. Das Objekt, auf das diese Eigenschaft verweist, sollte die Eigenschaft X509CertificateEndpointIdentity genaue Art.

Ich habe diese Lösung nicht getestet, aber sie erscheint mir sehr sinnvoll.

HTH Pedro

2voto

Zeratul Punkte 29

[UPDATE] Bei der Einstellung certificateValidationMode auf none gesetzt wird die Ausnahme verschwinden lässt, ist es inakzeptable Lösung aus Sicherheitsgründen Standpunkt aus gesehen.

Es macht den Kunden dass er ''irgendein'' Zertifikat erhält, ohne auf Einzelheiten einzugehen. Diese macht Angriffe möglich. Es wird immer noch nicht die vom Dienst gesendeten Informationen (angeblichen) Dienst gesendeten Informationen gegen das Zertifikat, das in der Konfiguration hinterlegt ist.

Sie irren sich. Das wird perfekt funktionieren. Das ist genau das, was Sie wollen - Ihr Zertifikat für no validiert werden. Dazu müssen Sie lediglich die Identität des Endpunkts auf dem Client auf

<identity>
  <certificate encodedValue="encoded certificate"/>
</identity>

Wenn sich der Client mit dem Server verbindet, vergleicht WCF die beiden Zertifikate und löst eine Ausnahme aus, wenn sie nicht übereinstimmen. Und Sie sind vollkommen sicher.

Die Verwendung eines benutzerdefinierten Validators wie Pedro Felix vorgeschlagen wird, ist in Ihrem Fall völlig unnötig. Genau dafür ist die Endpunktidentität gedacht.

2voto

ItsMe Punkte 241

Zu anderen Antworten kann ich leider nichts sagen.

Ich habe dies gerade in .NET 4.0 getestet und kann bestätigen, dass die Antwort von "Zeratul" richtig ist. Explizite Einstellungen der Identität des Dienstes entweder in der Konfiguration oder programmatisch ist ausreichend für die Server-Authentifizierung. Es besteht keine Notwendigkeit, das Zertifikat mit anderen Mitteln zu validieren (d.h. Sie können "certificateValidationMode" auf "None" setzen), da Sie die ultimative Validierungsmethode verwenden - den Vergleich des Thumbprints des Zertifikats.

@AlexDrenea

"serviceCertificate" wird nicht zur Validierung verwendet. Es wird zusammen mit der Nachrichtensicherheit verwendet, um Nachrichten zu verschlüsseln, bevor sie an den Server gesendet werden. Siehe hierzu die Dokumentation von Microsoft:

http://msdn.microsoft.com/en-us/library/ms731782.aspx

1voto

Zeratul Punkte 11

Dies ist ein zusätzlicher Kommentar zu meiner vorherigen Antwort. Leider kann ich keine Antworten kommentieren.

Außerdem tun Sie no einstellen müssen jede Identität auf dem Server. Vergessen Sie, was WSDL Ihnen über die Identität des Servers sagt. Die Identität eines Ferndienst-Endpunkts wird vom Client während der Laufzeit bestimmt. Wenn der Server SSL verwendet, hat er mehrere Identitäten: den gemeinsamen Namen des Zertifikats (d. h. eine DNS-Identität), eine Zertifikatsidentität und eine RSA-Identität (bei der letzten bin ich mir nicht sicher). Daher können Sie die Identität des Servers anhand eines dieser Kriterien (oder mehrerer) überprüfen.

0voto

AlexDrenea Punkte 7865

Sie sind fertig und haben die Konfiguration des Clients fast abgeschlossen. Eine letzte Sache fehlt noch (wie in der Fehlerbeschreibung erwähnt): Sie müssen in der Konfiguration den revocationMode auf NoCheck setzen:

 <behaviors>
  <endpointBehaviors>
    <behavior name="SecureMessageUserName">
      <clientCredentials>
         <serviceCertificate>
            <authentication revocationMode="NoCheck"/>
         </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
 </behaviors>

Wenn Sie weitere Details benötigen, lassen Sie es mich wissen, und ich werde eine vollständige funktionierende Client-Konfiguration veröffentlichen.

編集部 Entschuldigung für die Verzögerung

Sie sollten auch noCheck in der Serverkonfiguration hinzufügen:

<behavior name="X509SecureBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <serviceCertificate storeName="My" storeLocation="CurrentUser" x509FindType="FindByThumbprint" findValue="aaaa" />
            <clientCertificate>
              <authentication certificateValidationMode="None" revocationMode="NoCheck" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>

Außerdem habe ich den Verweis auf das Zertifikat nicht in die Endpunktdefinition aufgenommen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X