HowTo: Cross Domain Ajax mit JSONP und ASP.NET

image Eigentlich kann man Ajax Requests nur an Adressen senden die unter der gleichen Domain erreichbar sind wie die Seite auf der das Script ausgeführt wird. Der Grund dafür ist die Same Origin Policy in Javascript, diese besagt das der Port, das Protokoll und die Domain gleich sein müssen um Anfragen starten zu dürfen. Das ist zwar sicher, aber leider nicht immer praktisch.


Aber da gibt”™s doch bestimmt einen Trick?

Ja. Es gibt sogar eine ganze Menge verschiedener Möglichkeiten das Problem zu umgehen. Wenn man nach “Cross Domain Ajax” such bekommt man einen bunten Strauß an Lösungen, ich hab bestimmt einen halben Tag gebraucht um mir die verschieden Lösungen anzuschauen. Man könnte einen zum Beispiel einen Proxy einsetzen oder Flash/Silverlight nutzen usw… Für mich war die beste Lösung JSONP zu nutzen.

 

Was ist JSONP?

JSONP steht für “JSON with padding”. Die Idee ist so simpel wie Clever, man macht sich eine Sicherheitslücke in der Implementation der Same Origin Policy der Browser zu nutze. Man kann zwar keine Requests zu anderen Domains starten aber man kann dynamisch Javascript Dateien von anderen Domains einbinden. Und in diese packt man einfach seine Daten. Das Ganze hat den Nachteil das man Daten nur per GET übergeben kann und kein POST möglich ist. Wer mehr Daten übertragen möchte kann allerdings auf andere Tricks zurückgreifen oder muss sich etwas einschränken.
jQuery macht die Implementation an dieser Stelle wieder sehr einfach und gibt uns die entsprechenden Methoden an die Hand.

Und so sieht”™s aus

 
Auf dem Client:
      $.ajax({
                dataType: 'jsonp',
                jsonp: 'jsonp_callback',
                url: 'http://localhost:56761/TestService.ashx',
                success: function (j) {
                    alert(j.response);
                },
            });     

Der Unterschied zum “normalen” jQuery Request ist eigentlich nur die Zeile “jsonp: ‘jsonp_callback’” diese gibt den GET Parameternamen an in dem jQuery den Namen der Calback Funktion an den Server übermittelt.

Bei jQuery funktioniert das ganze so:

  1. Es wird ein <script> Tag erzeugt das auf die angegebene Adresse verweist, dabei wird als Parameter wird eine Zufallszahl übergeben(das ist dann der Name der Callbackfunktion).
  2. Der Server baut als Antwort eine Javascript-Datei zusammen die eine Funktion mit dem Namen der Zufallszahl aufruft und die Daten im JSON Format übergibt.
  3. Der Browser bindet das Script ein und führt das ganze aus. jQuery übergibt uns jetzt die Daten an das “success” Event.
Und auf dem Server:
string response = context.Request.Params["jsonp_callback"];
       response += "({\"response\":\"" + context.Session["RequestCounter"]  + " requests startet\"});";
context.Response.Write(response);

image

Für dieses Beispiel habe ich einen Generic Handler (.ashx) benutzt. Man könnte sicherlich auch einen WCF benutzen.

Die Beispielanwendung besteht aus zwei Projekten, einen Client das “CrossDomainAjax” Projekt und einen Service dem “SourceDomain” Projekt. Um die Demo zu starten müsst ihr mit:

Rechtsklick auf den Projektnamen -> Debug -> Start New Instance

Beide Projekte starten. Danach solltest du dann ein alert mit einer 1 im Browser sehen. Mit diesen Beispiel habe ich noch ausprobiert ob ich auf dem Server dann auch Zugriff auf die Sessesion habe. Und es geht. Bei jeden neu laden der Seite erhöht sich dann der Wert um eins. Gut, das ist jetzt kein spannendes Beispiel aber ich hoffe ihr verzeiht mit das :)

Den Demo Code gibt”™s hier. Viel Spaß.


Kick It auf dotnet-kicks.de
Wenn dir der Blogpost gefallen hat, dann hinterlasse doch einen Kommentar. Wenn du auf dem Laufenden bleiben willst, abonniere unseren RSS Feed oder folge uns auf Twitter.

About the author

Written by Oliver Guhr

Currently there is no additional info about this author.

5 Responses

  1. Sehr interessanter Ansatz, muss ich bei Gelegenheit direkt mal ausprobieren. Aber holt man sich damit nich auch irgendwo ne riesen Sicherheitslücke ins Haus?

    Reply
  2. Grundsätzlich, nein, also nicht mehr als bei jeden anderen Web Service. Es könnte sein das man deinem Javascript Code per XSS eine andere Web Service Adresse unterschiebt, die Frage ist ob das dem Angreifer was bringt.

    Reply
  3. Hallo,
    danke für die Tipps. Ich war schon am Verzweifeln, weil ich von dieser Sicherheitsmaßnahme nichts wußte. Leider liefert Firefox keinen Fehler, sondern nur Status=0.
    Erst Opera zeigte den Fehler in der Fehlerkonsole.
    Ich nutze aber lieber einen Proxy. Das erscheint mir sauberer und vor allem zukunftssicherer. Denn wer weiß, wie lange dieses Workaround noch funktionieren wird:

    Hier mein Beispiel anhand von google maps
    Diese Datei liefert schön valided XML an den AJAX-Ausruf.

    Datei: proxy.php

    header(‘Content-type: text/xml; charset=”utf-8″‘,true);
    readfile(‘http://maps.google.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false‘);

    Reply
  4. Hallo Jürgen,

    natürlich ist der Proxyansatz deutlich eleganter – allerdings gibt es genügend Fälle wo man keine Chance hat einen Proxy einzusetzen oder aber man möchte es den Benutzer möglichst einfach machen wie z.B. bei der Einbindung eines Widget. Als Beispiel mal das Widget von Twitter .. ich glaube nicht das viele Leute es einbinden könnten, wenn man noch serverseitig einen “Proxy” einbinden müsste. Selbst wenn es sich hier um einen simplen Kopiervorgang geht…

    Wie gesagt, bei einer eigenen Lösung die man nicht auf andere Websiten verteilen möchte ganz klar Proxy.. ansonsten halt wie hier beschrieben.

    Viele Grüße
    Daniel

    Reply

Comment on this post

Letzte Posts

  • Carriage Return / Neue Zeile in Textareas

    Eine kleine Aufgabe: Jede neue Textzeile (Carriage Return/Wenn man Enter drückt ) in einer Textarea soll ein Element in einer Auflistung sein – wie mach ich das jetzt am einfachsten? Eigentlich ein grundlegendes Element im Web und der Nutzer macht bewusst Absätze – daher wäre es nur gerecht, wenn man das auch entsprechend würdigt. Kleine ...

  • image.png
    Doom, Quake, Wolfenstein & co. Source Code auf GitHub

    id Software, die Macher von Doom, Quake, Wolfenstein & co., stellen regelmäßig ihre älteren Spieltitle als Open Source zur Verfügung. Das Ganze runterzuladen fand ich bisher immer recht mühselig, allerdings gibt es seit kurzer Zeit die Sourcen auch auf GitHub. Darunter Spiele wie Doom 3, Quake 3, Wolfenstein für iOS. Wer also schon immer mal ...

  • image.png
    Twitter Bootstrap 2.0 released & “Release Präsentation”

    Wie bereits vom Twitter Bootstrap Team angekündigt wurde offiziel die Version 2.0 des UI Toolskits “Twitter Bootstrap” veröffentlich. Zudem wurden die Slides, welche bei der Release Party gezeigt wurden auch veröffentlicht: Downloads finden sich auf der Twitter Bootstrap Seite auf GitHub. Wenn dir der Blogpost gefallen hat, dann hinterlasse doch einen Kommentar. Wenn du auf ...

  • image.png
    Javascript zu Dart Translator

    Dart, Google Javascript Alternative, wurde vor ein paar Monaten vorgestellt und die Webentwickler Szene ist noch etwas gespalten, ob Dart nun überflüssig ist oder einfach nur cool und längst überfällig ist. Um die Sprache näher zu erläutern hat Google die grundlegenden Javascript Basics nach Dart übersetzt. Das Ergebnis ist der “Translator”. Der Name mag momentan ...

  • Twitter Bootstrap 2.0–“Beta”

    Twitter Bootstrap, ein UI-Toolkit für Web-Applikationen von Twitter, erscheint (wie bereits berichtet) demnächst in der Version 2.0. Der offizielle Release ist am 31. Januar, allerdings beginnt jetzt laut Mark Otto (einer der Hauptentwickler von Twitter Bootstrap) die intensive Test-Phase. Das heisst, das es nun offiziel auch die 2.0 Dokumentation online gibt. Im Vergleich zur aktuellen ...

Support us!

Facebook