| 

.NET C# Java Javascript Exception

4
Hallo liebe codekicker-Community,

ich stehe hier vor einem riesigen Problem und umfangreiche Recherchen haben zu keinen Ergebnissen geführt.

Ziel
Zurzeit versuche ich einen HTTPS-WebService einzurichten, der über WCF in einem selbst-gehosteten Windows-Dienst laufen soll. Ich habe bereits mehrere solcher Dienste eingerichtet, nur bisher nicht über HTTPS (SSL).

Anforderungen an den WebService
Einen Dienst, der von Außen angesprochen werden kann und über HTTPS (SSL) läuft, habe ich erfolgreich einrichten können.
Was ich aber brauche, ist nicht ein Dienst, der sich gegenüber dem Client authentifiziert, sondern der Dienst soll auch den Client selbst authentifizieren.
Das heißt, ich möchte das Zertifikat vom Client erhalten und im Server (Dienst) überprüfen (gerne manuell).

Beispiel zum Testen
Ich habe zum Testen einen Dienst aufgebaut, der äußerst simple ist:
[ServiceBehavior()]
class WcfCertificateService : IWcfCertificateService
{
public string SendMessage(string message)
{
return String.Format("You send: {0}", message);
}
}


IIS steht nicht zur Verfügung
Zum Thema IIS finde ich im Netz einiges an Informationen und mit dem IIS könnte ich sofort den Service einrichten. Leider gibt es Gründe, die ich hier nicht näher ausführen möchte, die mich aber zwingen, dass der HTTPS-WebService selbst-gehosted wird.
Hier ist eine Seite, welche mein Ziel beschreibt. Aber ich möchte das Ziel ohne IIS erreichen.

Lösung im IIS
Das hier möchte ich ohne IIS erreichen (Beispiel zeigt die Einstellung im IIS):

(siehe auch HIER unter dem Satz "Our configuration of our WCF service binding was as following:")

Kernpukte
Dieser Schalter macht mir in meiner app.config immer Probleme:
<basicHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>


Wenn man den Wert "Certificate" bei clientCredentialType auf "None" stellt, dann kann der Client problemlos mit dem Server kommunizieren. Dadurch wird aber auch die Identität des Client unterdrückt und ich kann das Zertifikat im Server nicht überprüfen.
Wenn ich den Wert aber auf "Certificate" stelle, dann erhalte ich folgende Meldung (Exception):

System.ServiceModel.Security.MessageSecurityException occurred
Message=Die HTTP-Anforderung wurde mit Clientauthentifizierungsschema "Anonymous" nicht zugelassen.
Source=mscorlib
StackTrace:
Server stack trace:
bei System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory factory)
bei System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException, ChannelBinding channelBinding)
bei System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
bei System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
bei System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
bei System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
bei System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
bei System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
bei System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
bei System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
bei System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
bei WcfCertificateTestBaseLibrary.IWcfCertificateService.SendMessage(String message)
bei WcfCertificateTestClientConsoleApplication.WcfCertificateClient.SendMessage(String message)
InnerException: System.Net.WebException
Message=Der Remoteserver hat einen Fehler zurückgegeben: (403) Unzulässig.
Source=System
StackTrace:
bei System.Net.HttpWebRequest.GetResponse()
bei System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)


Schlussfolgerung
Bei diesem Problem bin ich inzwischen schon ziemlich weit gekommen und habe auch viele verschiedene Versuche unternommen, die ich hier niemals alle bis ins Detail beschreiben könnte.

Das Problem liegt in jedem Fall am Server.
Denn der Client funktioniert, wenn man den Server in einem IIS hosted.
Aber wie gesagt: diese Option habe ich leider nicht, nur die Möglichkeit es in einem IIS zu testen (und das auch nur bedingt).

Es könnte mit den Zertifikaten zusammenhängen, da es sich um Zertifikate handelt, die ich mit "makecert" generiert habe. Ich bin dabei zwar äußerst genau vorgegangen, aber auch da kann mir ein Fehler unterlaufen sein.
Wenn jemand mir also mitteilen kann, wie man für die Entwicklungsumgebung brauchbare Zertifikate erstellt, dann wäre das vielleicht auch hilfreich.
HIER habe ich die Informationen hergeholt, um die Zertifikate zu erstellen.
Nur den letzten Schritt (mit IIS) konnte ich nicht ausführen. Dazu habe ich den Befehl mit "NETSH" benutzt.
netsh http add sslcert ipport=1.2.3.4:443 certhash=[Thumbprint vom Zertifikat des Servers] appid={GUID}


Frage
Was könnte ich übersehen haben?

Ich habe im Internet (Google) nach diesen Begriffen gesucht und nahezu hunderte von Seite durchforstet:
self-hosted, wcf, https ssl, mutual authentication, client certificate, client credentials

Vielleicht habe ich etwas übersehen oder das Problem ist nicht so groß wie es scheint.
Auf jeden Fall hänge ich schon seit Tagen an diesem Fehler.

Bitte, hilft mir (O-.-O)
22.08.2013
Marcus.D 86 1 4
2 Antworten
2
Lies mal hier und hier. Vielleicht hilft Dir das weiter.
22.08.2013
JEwen 2,7k 5
Diese Beiträge kenne ich bereits, aber hatten mir leider nicht helfen können.
Mir würde sicherlich eine exemplarische Vorgehensweise weiterhelfen, welche den Einsatz von SSL und WCF mit Zertifikaten in einem selbst-gehosteten Dienst darstellt.
Aber das ist anscheinend selbst für Google zu speziell.
Marcus.D 26.08.2013
0
Danke für die Antwort.

In diese Richtung habe ich auch gedacht, denn die Bindung eines Zertifikats an einen Port ist eine der Einstellungen, die man machen muss, wenn man keinen IIS benutzt.
Bei dem einen Artikel "How to: Configure a Port with an SSL Certificate" habe ich verschiedene Varianten ausprobiert.
Diese Einstellung ist besonders wichtig, weil man sonst folgende Fehlermelung im Client erhält:
Fehler beim Erstellen der HTTP-Anforderung für https://1.2.3.4/WcfCertificateService/. Dies ist möglicherweise darauf zurückzuführen, dass das Serverzertifikat im Fall von HTTPS nicht ordnungsgemäß mit HTTP.SYS konfiguriert wurde. Eine andere mögliche Ursache kann eine fehlende Übereinstimmung bei der Sicherheitsbindung zwischen Client und Server sein.

Wenn ich die Einstellung setze und Parameter benutze wie "ipport=...", "certhash=...", "appid=...", dann erhalte ich diesen Fehler nicht mehr.
Das reicht auch aus, damit der Client den Server authentifizieren kann, denn auf der Client-Seite kommt das Serverzertifikat auch an, wenn ich es nie im Programmcode abrufe oder in der Konfiguration erwähne.
Auf der MSDN-Seite habe ich aus den Punkt "To bind an SSL certificate to a port number and support client certificates" entdeckt.
Und genau das möchte ich erreichen...
support clients that authenticate with X.509 certificates at the transport layer

Also habe ich folgenden Befehl eingegeben...
add sslcert ipport=0.0.0.0:443 certhash=[Mein Thumbprint] appid={GUID} clientcertnegotiation=enable

Ich dachte, dass genau der Parameter "clientcertnegotiation=enable" die Lösung wäre, aber der Effekt blieb aus.
Jetzt erhalte ich wieder den Fehler...
Die HTTP-Anforderung wurde mit Clientauthentifizierungsschema "Anonymous" nicht zugelassen.


Den Datenaustausch habe ich auf beiden Seiten (Server und Client) einmal getraced, indem ich "System.Net" überwacht habe:
<configuration>
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex" maxdatasize="1024">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Cache">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Security">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
<add name="System.Net.Cache" value="Verbose"/>
<add name="System.Net.Security" value="Verbose"/>
</switches>
<sharedListeners>
<add name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="network.log"
/>
</sharedListeners>
<trace autoflush="true"/>

</system.diagnostics>

Und jetzt wird es interessant.
Im Trace stand folgende Meldung:
System.Net Information: 0 : [6612] SecureChannel#44115416 - Wir verfügen über vom Benutzer bereitgestellte Zertifikate. Der Server hat 133 Aussteller angegeben. Es wird nach Zertifikaten gesucht, die mit einem der Aussteller übereinstimmen.
System.Net Information: 0 : [6612] SecureChannel#44115416 - Noch 0 Clientzertifikate zum Auswählen verfügbar.
System.Net Information: 0 : [6612] Das zwischengespeicherte Anmeldeinformationshandle wird verwendet.

Den ganzen Trace werde ich nicht posten, aber wie es scheint, muss ich im Server irgendwo definieren, welche Zertifikate er als Clientzertifikate akzeptiert.
Hier ist von Ausstellern die Rede, aber weiter bin ich da noch nicht gekommen.
23.08.2013
Marcus.D 86 1 4

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH