5 Stimmen

Signieren von WCF-Nachrichten mit einem Zertifikat über HTTPS-Transport mit Client-Zertifikat

EDIT:

Ich habe schließlich festgestellt, dass IClientMessageInspector nicht zu reflektieren scheint Nachricht signieren, so dass, wenn ich tatsächlich eine Signatur in meiner Anfrage bekam ich es nicht wissen. Also jetzt für meine neue, echte Frage ...

Wie kann ich einen WCF-Client so konfigurieren, dass er sowohl das SSL-Client-Zertifikat vorlegt als auch den SOAP-Header signiert?

var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;

Dies führt dazu, dass die Kopfzeile einen signierten Zeitstempel enthält. Allerdings wird das Client-Zertifikat nicht mehr angezeigt, und ich komme nicht über SSL hinaus. Wenn ich die zweite Zeile ändere in:

myBinding.Security.Mode = BasicHttpSecurityMode.Transport;

Dann komme ich an SSL vorbei, aber mein SOAP-Header enthält nicht mehr den Signierungsblock.

Gibt es eine Möglichkeit, wie ich HttpWebRequest erreichen kann, so dass ich das SSL-Client-Zertifikat manuell wie so anhängen kann?

webRequest.ClientCertificates.Add(certLoader.Load(@"c:\somecert.pfx"));

Ursprüngliche Frage

Ich arbeite an einem WCF-Client, der mit einem Dienst zusammenarbeiten muss, der von einem Drittanbieter bereitgestellt wird, der eine Forum Sentry-Netzwerkanwendung für den sicheren Zugriff verwendet. Sie erfordern SSL mit einem Client-Zertifikat auf der Transportebene sowie ein o:Security-Element mit Signatur unter Verwendung eines Zertifikats im Header. Ich bin in der Lage, das eine oder das andere mit Standardbindungen zu erreichen, aber ich scheine nicht in der Lage zu sein, beides gleichzeitig zu erreichen. Im Idealfall soll die Nachricht mit einem anderen Zertifikat als dem SSL-Client-Zertifikat signiert werden, aber sie sagten, wir könnten dasselbe Zertifikat sowohl für die SSL-Client-Authentifizierung als auch zum Signieren der Nachricht verwenden.

Ich bin bereit, alles an dieser Stelle zu tun, um dies zu arbeiten, einschließlich der Verwendung einer CustomBinding, wenn nötig.

Ich kann den SSL-Teil wie folgt zum Laufen bringen:

var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.Transport;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var url = "https://blah.com/services/somservice";
EndpointAddress ea = new EndpointAddress(url);
var client = new SoapClient(myBinding, ea);
var certLoader = new CertificateLoader("password");
client.ClientCredentials.ClientCertificate.Certificate = certLoader.Load(@"c:\somecert.pfx");
var resp = client.somemethod(ref profile, new RequestType { version = RequestTypeVersion.Item100 });

2voto

Yaron Naveh Punkte 22631

Bitte veröffentlichen Sie ein Beispiel für eine funktionierende Soap (z.B. eine, die der Anbieter zur Verfügung gestellt hat). Übrigens gibt es viel drastischere Maßnahmen als die Verwendung einer benutzerdefinierten Bindung :)

Bearbeiten: Um sowohl Transport- als auch Nachrichtensicherheit zu verwenden, benötigen Sie eine benutzerdefinierte Bindung. Googeln Sie nach "wcf binding converter", um dies automatisch zu tun. In der benutzerdefinierten Bindung anstelle von http-Element ändern Sie es in https und verwenden Sie das Attribut requirevlientcertificate. Entschuldigung für die Rechtschreibung ich bin auf dem Handy

EDIT:

var c = new CustomBinding();            
MessageSecurityVersion version = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
var sec = SecurityBindingElement.CreateCertificateOverTransportBindingElement(version);
c.Elements.Add(sec);
c.Element.Add(new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap11 };)
c.Elements.Add(new HttpsTransportBindingElement() { RequireClientCertificate = true });

0voto

JohnOpincar Punkte 5192

Das ist hässlich, aber es erfüllt seinen Zweck. Wenn Sie sich die Elemente jeder dieser benutzerdefinierten Bindungen im Debugger ansehen, werden Sie sehen, dass, obwohl beide ein HttpsTransportBindingElement am unteren Ende ihres Stapels haben, die TransportWithMessageCredential-Instanz RequireClientCertificate auf false und ein paar andere private Memebers in Bezug auf das Zertifikat auf false gesetzt haben wird. Bei der Transportinstanz werden diese Elemente auf true gesetzt. Dies ist eindeutig ein Fehler in WCF, IMO.

Der folgende Code nimmt das "gute" HttpsTransportBindingElement aus der customTransportSecurityBinding und ersetzt das "schlechte" in der customMessageCredentialBinding. Anschließend übergeben Sie das geänderte customMessageCredentialBinding an Ihren Client-Konstruktor.

    var transportSecurityBinding = new BasicHttpBinding();
    transportSecurityBinding.Security.Mode = BasicHttpSecurityMode.Transport;
    transportSecurityBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    transportSecurityBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
    var customTransportSecurityBinding = new CustomBinding(transportSecurityBinding);

    var messageCredentialBinding = new BasicHttpBinding();
    messageCredentialBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
    messageCredentialBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    messageCredentialBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
    var customMessageCredentialBinding = new CustomBinding(messageCredentialBinding);

    // replace transport binding element from message credential binding with the transportSecurityBinding transport binding
    // which will include the cert for SSL mutual auth.
    customTransportSecurityBinding.Elements[customTransportSecurityBinding.Elements.Count - 1] = customMessageCredentialBinding.Elements[customMessageCredentialBinding.Elements.Count - 1];

var client = new SomeSoapClient(customTransportSecurityBinding, ea);

0voto

Arsalan Saleem Punkte 321

Für den Fall, dass jemand für app.config Version von benutzerdefinierten Bindung für die obige Antwort suchen:

<bindings>
      <customBinding>
        <binding name="SignedMessageBinding">
          <security messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" /> 
          <textMessageEncoding messageVersion="Soap11" />
          <httpsTransport requireClientCertificate="true"  />
        </binding>
      </customBinding>
</bindings>

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