Domänenübergreifende Ajax-JSON-POST-Unterstützung für den RESTful-WCF-Dienst mithilfe der TransportCredentialOnly-Sicherheit

8

Ich habe schon vorher zu diesem Thema geschrieben, aber nach einem Jahr, in dem ich mich mit anderen Dingen beschäftigt habe, ist es mir wieder einmal gelungen, in eine Gurke zu geraten. Ich werde versuchen, einen kurzen Überblick über das Szenario und die aktuellen Versuche zu geben, die Dinge funktionieren zu lassen:

  • IIS-Webserver, der HTML, JS usw. auf dem Host hostet: iis.mycompany.com (bezeichnet als foo )
  • WCF REST-konforme Web-Services, die über einen Windows-Dienst auf dem Host gehostet werden: wcf.mycompany.com (bezeichnet als Leiste )

Das von foo bereitgestellte Javascript funktioniert, indem RESTful-Ajax-Aufrufe ( GET oder POST abhängig von der Aktion) an die WCF-Dienste in bar gesendet werden sind domainübergreifende Aufrufe, da sie sich nicht auf demselben Host befinden.

Das Javascript verwendet das jQuery (1.7.2) -Framework, um das DOM zu manipulieren und Ajax-Aufrufe an bar auszuführen. Der erwartete Inhaltstyp für POSTS ist JSON und die Antwort von GETS wird voraussichtlich auch JSON sein (application / json).

Leiste hat seine WCF-Dienste mit TransportCredentialOnly als Sicherheitsmodus konfiguriert, und der Transportclient-Typ ist NTLM , also nur autorisierte Benutzer, die die Dienste kontaktieren.

CORS-Unterstützung wurde den WCF-Diensten der Leiste hinzugefügt, die eine Erweiterung von WCF verwenden:

Ссылка

Wir haben zusätzliche Header hinzugefügt und einige, die der Post bereits enthielt, basierend auf zahlreichen Internetartikeln modifiziert:

%Vor%

Sites, die Informationen zur Aktivierung von CORS geben, schlagen vor, dass der Header Access-Control-Allow-Origin response auf "*" gesetzt werden sollte, dies ist jedoch in unserem Fall nicht möglich, da wir jQuery-Ajax-Aufrufe mit folgendem Setup durchführen:

%Vor%

Wie sich herausstellt, können Sie "*" nicht für den akzeptierten Ursprung verwenden, wenn Sie "withCredentials" im Ajax-Aufruf verwenden:

Ссылка

  

"Wichtiger Hinweis: Wenn Sie auf eine Credential-Anfrage antworten, Server   muss eine Domain angeben und darf keine Platzhalter verwenden. "

In unserem Entwicklungslabor spielt dies keine Rolle, da wir die Anfragen hart an die IIS (foo) Server-URL kodieren können.

Das Hauptproblem scheint jetzt zu sein, POST Anfragen zu versuchen ( GET arbeitet mit der obigen Konfiguration). Wenn der Browser den POST -Prozess versucht, sendet er zuerst einen OPTIONS -Header an den Server und fordert OPTIONS für den nachfolgenden Post an. An dieser Stelle möchten wir sehen, dass die Header, die wir in der WCF-Erweiterung von CORS Support konfiguriert haben, zurückgegeben werden, aber wir kommen nicht so weit. Bevor die Antwort als "401 Unauthorized" zurückkommt, glaube ich, dass dies mit der Transportsicherheitsbindungskonfiguration zu tun hat, die NTLM anfordert, aber ich bin mir nicht sicher.

Ich bin auch nicht sehr erfahren, aber ich habe nicht viele Informationen über POST mit application/json Inhaltstyp im Gegensatz zu text/plain bei der Ausführung von domänenübergreifenden Anfragen gesehen.

Ich weiß, dass die Leute wahrscheinlich JSONP als die einzig wahre Lösung vorschlagen werden, ich bin nicht gegen verschiedene Ansätze, in der Tat ermutige ich jeden, Best Practices vorzuschlagen, da es anderen helfen würde, diese Frage später zu lesen. Versuchen Sie jedoch, die Frage zu beantworten, bevor Sie Alternativen vorschlagen.

Vielen Dank im Voraus für jeden, der dazu beiträgt.

peteski :)

UPDATE:

Es scheint, dass Chrome (20.x.x) nicht das Problem hat, NTLM nicht zu verhandeln, um die Header-Antwort OPTIONS vom Server abzurufen, sondern Firefox (13.0.1).

Wir haben auch bemerkt, dass jemand bereits einen Fehler im Firefox-Forum gepostet hat, zu dem wir Informationen hinzugefügt haben:

Ссылка

Bitte stimme ab, dass dieser Bug auf der Bugzilla-Seite behoben wird!

Mit dem folgenden Code können wir den Netzwerk-Trace überwachen, um zu sehen, dass Firefox nicht funktioniert und Chrome funktioniert einwandfrei:

%Vor%

Auf einer separaten Notiz unterstützt IE8% ce_de% nicht für domänenübergreifende Aufrufe und favorisiert sein eigenes magisches XMLHttpRequest -Objekt. Daher müssen wir etwas tun, um den clientseitigen Code zu ändern, um IE8 vs zu behandeln die Weltfälle. (Danke IE8).

/ me kreuzt die Finger, dass Mozilla den Firefox-Bug behebt.

UPDATE 2:

Nach einigen Ausgrabungen scheint es, dass IE8 XDomainRequest nicht verwendet werden kann, um domänenübergreifende Anfragen zu stellen, bei denen NTLM ausgehandelt werden muss. Dies bedeutet im Grunde, dass die Sicherheit unserer WCF-Bindung aufgrund von Einschränkungen in einem Webbrowser nicht verwendet werden kann.

Ссылка

  

"Keine Authentifizierung oder Cookies werden mit der Anfrage gesendet"

Also, ich nehme an, wir haben das so weit gebracht, wie es jetzt gehen wird ..Es sieht so aus, als müssten wir unsere eigene benutzerdefinierte Token-Authentifizierung erstellen und sie an den WCF-Dienst in einem Cookie weitergeben, oder im Fall von IE8, XDomainRequest it mit dem JSON. Der WCF-Dienst muss dann die Daten entschlüsseln und diese anstelle von POST verwenden, auf die wir zuvor mit NTLM-Authentifizierung Zugriff hatten.

    
peteski 04.07.2012, 14:19
quelle

1 Antwort

1

Ich weiß, dass Sie gesagt haben, dass Sie das Problem lieber selbst ansprechen würden, aber Sie könnten einen "Reverse Proxy" in Betracht ziehen.

Ich weiß nicht, welche Technologien Sie verwenden, aber wir verwenden den Apache-Webserver und eine Java-RESTful-API, die auf einem anderen Server ausgeführt wird, der eine Authentifizierung erfordert. Für eine Weile haben wir uns mit JSONP und CORS beschäftigt, waren aber nicht zufrieden.

Am Ende haben wir einen Apache Reverse Proxy eingerichtet und es hat Wunder gewirkt. Der Webbrowser glaubt, dass er mit seiner eigenen Domäne kommuniziert und entsprechend handelt. Die RESTful-API weiß nicht, dass sie über einen Proxy verwendet wird. Daher funktioniert alles einfach. Und Apache macht all die Magie.

Hoffentlich haben alle Webserver eine Funktion wie der Reverse Proxy von Apache. Hier finden Sie einige Dokumentationen zum Feature: Ссылка

Alles, was wir tun mussten, ist sicherzustellen, dass das mod_proxy-Modul installiert wurde. Fügen Sie dann die folgenden Zeilen zu unserer Apache-Konfigurationsdatei hinzu:

%Vor%

Dann starte den Webserver neu und voila!

    
Nostalg.io 18.12.2013 18:41
quelle