JavaScript sichere Ajax <-> REST Api Kommunikation (https?)

CitroenDsVier

Lt. Commander
Registriert
Dez. 2013
Beiträge
1.885
Hallo zusammen,

ich möchte eine Webanwendung bauen, die aus separatem Front- und Backend besteht. Das Backend wird mit Java in Form einer REST Api (entweder Sparkjava oder Spring Boots) realisiert, das Frontent wird normales html, css, javascript.

Aktuell soll die Kommunikation zwischen GUI und Backend über AJAX-Requests laufen, die die erforderlichen Daten vom Backend abfragen. Da die ganze Sache aber auch sicher sein soll, frage ich mich, ob und wie so eine Kommunikation abgesichert werden kann. Eine Verschlüsselung im Javascript kann man sich vermutlich schenken, weil jeder den Quellcode einsehen und damit die Verschlüsselung nachvollziehen kann.
Da der Webserver für das Frontend aber vermutlich auf einem anderen Server läuft, als das Backend, bin ich mir nicht sicher, ob HTTPS hier realisierbar ist.

Kann mir dazu Jemand genauere Auskunft geben?

MfG
 
Wenn du mit dem Backend über https kommunizierst ist das per se sicher, da der Header, und alles hinter dem Host durch SSL verschlüsselt wird inkl. Parameter. Du brauchst dann nichts zusätzliches machen.

Wichtig ist nur dass der Backendserver nur per https erreichbar ist und das Zertifikat gültig ist. Nur dann klappt auch die Kommunikation. Und um sicherer zu sein kannst du beim Backend auch über CORS festlegen, welche Domains überhaupt mit dem Backend kommunizieren dürfen. Alle Calls von Clients von anderen Domains werden dann direkt vom Browser abgelehnt.

Und egal was der Client schickt. Niemals vertrauen. Ein Client ist immer böse.
 
Verstehe ich dich richtig?

Server (Backend)
  • Ist ein Webserver der mittels HTTP(s) Verbunden wird
  • Der Webserver bzw. dessen Logik ist in Java umgesetzt

Client (Frontend)
* Browser basiert (HTML, CSS, JS)

Alles was Verbindungsverschlüsselung angeht passiert also auf dem Apllication Layer (HTTP(s)). Was du über diesen Layer am Schluss laufen lässt ist egal und hat kein Einfluss auf die Verschlüsselung. [1]

[1] Wenn doch, bitte nochmal den Grundkurs Netzwerke besuchen

Edit:
GHad schrieb:
Und egal was der Client schickt. Niemals vertrauen. Ein Client ist immer böse.
@GHad ich mag deinen Pessimismus!
 
Ist kein Pessimismus, ist Realität:

  • Der Server kann sich identifizieren, der Client nicht
  • Der Server läuft mit seinem nicht manipulierbarem kompilierten Code, der Client im Browser, ändern einfach per Dev-Tools Console

Und daher ist jede Art der Übermittlung vom Client erst mal potentiell kontaminiert und muss serverseitig überprüft werden.
 
@GHad: Von CORS habe ich mal gehört, habe hier aber noch nicht daran gedacht. Das würde ja bedeuten, dass mein Vorhaben, das Frontend von einem separaten Webserver zu hosten, von vornherein scheitern würde, weil ich keine ajax requests auf den server meines backends machen könnte. (?)

Dann ist es vermutlich das Beste, wenn die REST-Api gleichzeitig den Webserver für das Frontend darstellt, oder?

@Piktogramm: Ursprünglich dachte ich, das Frontend von einem separaten Webserver zu hosten, aber wie gesagt ist es vermutlich besser, alles über die REST-Api zu hosten? (a lá "GET-Request auf "/" --> schicke index.html")
 
Ganz und gar nicht, exakt dafür ist CORS ja da, daß man das definieren kann.

Aber so richtig steig ich da nicht durch, was Du meinst. Wie soll eine API etwas darstellen? Die liefert nur die Daten, daß die Darstellung woanders läuft ist der SINN von AJAX und Co.

Daher:
  • static.website.lan liefert index.html, index.jpg, index.css und index.js (als Beispiel).
  • ajax.website.lan liefert zB ein JSON-Objekt mit den dynamischen Daten, die angezeigt werden sollen.
Mehr noch, die Daten via static* sind unkritisch und können prinzipiell(!) über http.
Die über ajax.* sind es nicht und "müssen" , ie sollten nach Möglichkeit, über https.


Wenn ein Webserver auf GET / eine Datei index.html liefert, dann ist das ganz normales Vorgehen und hat mit REST oder AJAX oder sonstwelchen APIs überhaupt nichts zu tun.
 
RalphS schrieb:
Ganz und gar nicht, exakt dafür ist CORS ja da, daß man das definieren kann.
aah, das habe ich dann falsch verstanden.

RalphS schrieb:
Wie soll eine API etwas darstellen? Die liefert nur die Daten
Eigentlich war es auch so geplant, dass sie nur die Daten liefert.

RalphS schrieb:
ajax.website.lan liefert zB ein JSON-Objekt mit den dynamischen Daten, die angezeigt werden sollen.
Genau so war es nämlich geplant :)

RalphS schrieb:
Mehr noch, die Daten via static* sind unkritisch und können prinzipiell(!) über http.
Die über ajax.* sind es nicht und "müssen" , ie sollten nach Möglichkeit, über https.
Und das war meine anfangs gemeinte Frage: Kann die Kommunikation über ajax zum Backend über https gesichert werden?

RalphS schrieb:
Wenn ein Webserver auf GET / eine Datei index.html liefert, dann ist das ganz normales Vorgehen und hat mit REST oder AJAX oder sonstwelchen APIs überhaupt nichts zu tun.
Da hatte ich mich vermutlich falsch ausgedrückt, ich meinte statt "REST-Api" im letzten Post viel mehr mein Backend, das ursprünglich nicht als Webserver, sondern nur als REST-Api geplant war, die dem Frontend eben die Daten über ajax-requests als JSON oÄ bereitstellt.
 
GHad schrieb:
Ist kein Pessimismus, ist Realität:
Meine Aussage war vollkommen zustimmend ohne jeden Hauch von Ironie :)

@Piktogramm: Ursprünglich dachte ich, das Frontend von einem separaten Webserver zu hosten, aber wie gesagt ist es vermutlich besser, alles über die REST-Api zu hosten? (a lá "GET-Request auf "/" --> schicke index.html")
An der Stelle wäre es hilfreich, wenn du mal ein Sequenzdiagramm rauslassen würdest :)
https://en.wikipedia.org/wiki/Sequence_diagram

Ansonsten nochmal, dem Applicationlayer auf dem du im Zweifelsfall die Verbindungsverschlüsselung hast, ist es total egal ob deine API restful oder -less ist. Vermisch bitte diese Dinge nicht. Es wirkt ganz schnell so, als würdest du Buzzwordbingo spielen anstatt zu verstehen was du tust.

Also nochmal:
Client fragt www.example.com an. Server1 beantwortet und liefert index.html und script.js neben anderen statischen Dateien aus. Client interpretiert *.html und *.js. Das JS bedingt nun, dass es Requests auf s2.example.com gibt. Diese Anfragen beantwortet Server2.
An der Stelle wäre mein Ansatz:
  • www.example.com liefert Dateien mittels http/2 aus (Daher mit aktiver Crypto und schön als Pipeline bzw. gleich so, dass wenn index.html angefragt wird, script.js gleich mit in die Pipeline gepusht werden). Die Verbindung wird nach dieser Aktion möglichst kurzfristig geschlossen.
  • Die Verbindung zu s2.example.com wird auch mit http/2 erschlagen.





RalphS schrieb:
Mehr noch, die Daten via static* sind unkritisch und können prinzipiell(!) über http.
Die über ajax.* sind es nicht und "müssen" , ie sollten nach Möglichkeit, über https.

Wenn ein Webserver auf GET / eine Datei index.html liefert, dann ist das ganz normales Vorgehen und hat mit REST oder AJAX oder sonstwelchen APIs überhaupt nichts zu tun.
Wo immer es geht sollte man für alles http/2 nutzen. Was Crypto erzwingt. Da bei http/2 wirklich alle Browser Pipelining und Push unterstützen kann man da Performance schinden und zwar mehr als man für den Overhead vom Crypto investieren muss.

Der 2. Absatz bekommt volle Zustimmung.
Ergänzung ()

CitroenDsVier schrieb:
Da hatte ich mich vermutlich falsch ausgedrückt, ich meinte statt "REST-Api" im letzten Post viel mehr mein Backend, das ursprünglich nicht als Webserver, sondern nur als REST-Api geplant war, die dem Frontend eben die Daten über ajax-requests als JSON oÄ bereitstellt.
Du vermischst immer noch verschiedene Layer, die prinzipiell wenig miteinander zu tun haben.
Edit2: Du nutzt Front- und Backend auch untypisch. Bitte lies den Wikipediaartikel: https://de.wikipedia.org/wiki/Front-End_und_Back-End
Bereits das erste Beispiel zu Client-Server trifft bei dir zu. Frontend läuft beim Clienten und alles was Daten an den Client liefert ist Backend..
 
Zuletzt bearbeitet:
CitroenDsVier schrieb:
@GHad: Von CORS habe ich mal gehört, habe hier aber noch nicht daran gedacht. Das würde ja bedeuten, dass mein Vorhaben, das Frontend von einem separaten Webserver zu hosten, von vornherein scheitern würde, weil ich keine ajax requests auf den server meines backends machen könnte. (?)

Dein Front-End läuft auf Server A unter www.citroendsvier.de. Deine API unter api.citroendsvier.de.
Der Browser erkennt nun, dass das zwei verschiedene Domains sind und wenn du eine Anfrage an deine REST API machst, fragt der Browser zuerst: "Hey ich komme hier von www.citroendsvier.de und würde gerne eine Abfrage machen. Darf ich das?" Der Server antwortet: "Ja, kein Problem. www.citroendsvier.de darf Daten abfragen."
Erst dann führt der Browser die richtige Abfrage durch.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
 
@Sparta8: Danke, dann habe ich den CORS Artikel richtig verstanden. Den von dir verlinkten Artikel habe ich gestern auch gelesen.

Piktogramm schrieb:
Wo immer es geht sollte man für alles http/2 nutzen. Was Crypto erzwingt. Da bei http/2 wirklich alle Browser Pipelining und Push unterstützen kann man da Performance schinden und zwar mehr als man für den Overhead vom Crypto investieren muss.
Die Frage ist, wie stelle ich eine solche Verbindung zwischen dem Front- und Backend in javascript als XMLHttpRequest her? Nach dem, was ich bisher gelesen habe, sei https dort nicht möglich. Wenn doch: wie? Sprich, was muss ich im Javascript tun? Den Server konfiguriere ich mit einem SSL Zertifikat für https, das ist machbar. Und dann führe ich die ajax requests einfach auf https://www.backend-server.de aus?
 
Zuletzt bearbeitet: (typo)
JS und XMLHttpRequest: https://stackoverflow.com/questions/43482467/does-http-2-work-in-cors-request
Grundsätzlich ist der Verbindungsaufbau Sache des Browsers und alles was nicht komplett veraltet ist, kann http/2. Wenn der Webserver also alle http Requests auf https umleitet und da Protokollversion 2 bevorzugt, sollte das hinhauen. Im Javascript solltest du dich da überhaupt nicht drum kümmern müssen. Im besten Fall schreibst du in alle urls direkt ein https:// statt http:// .

Was den Java Webserver angeht. Also Apache Spark nutzt nach kurzer Recherche Jetty als darunter liegenden Server und Jetty kann http/2 https://www.eclipse.org/jetty/documentation/9.4.22.v20191022/http2.html
Die Frage ist halt, ob Spark die Fähigkeiten von Jetty ordentlich exponiert.
Wenn es zu viel Aufwand bedeutet, musst du einfach abschätzen ob deine Zugriffsprofile von http/2 profitieren. Je mehr kurze Abfragen in kurzer Abfolge bzw. parallel erfolgen, desto eher lohnt http/s.

Ansonsten, wenn deine Logik vom Server nicht zu groß ist. Wäre es vielleicht auch ein Gedanken wert, ob du dein Backend mittels Node nicht auch in Javascript schreibst. Ich finde es ja immer merkwürdig, wenn Projekte ihre Logik auf 5+ Programmiersprache und mindestens ebensoviele Frameworks verteilen. Sowas wird meist die Wartungshölle und kollabiert mit dem Weggang weniger kritischer Entwickler.
 
Zuletzt bearbeitet:
Okay, danke! Dann versuche ich mich mal daran und melde mich ggf nochmal.

Piktogramm schrieb:
Was den Java Webserver angeht. Also Apache Spark nutzt nach kurzer Recherche Jetty als darunter liegenden Server und Jetty kann http/2
Hier bist du in die selbe Falle getappt wie ich am Anfang: Es handelt sich nicht um Apache Spark (Streamingsystem), sondern um "sparkjava" (website), eine Library, mit der man schnell eine laufende REST-Api zusammenbauen kann. Läuft aber ebenfalls auf Jetty. Ein erster Test (XMLHttpRequest von einer auf server1 gehosteten UI-Seite zum auf server2 laufenden Backend, welches CORS entsprechend konfiguriert hatte) lief allerdings mit http 1.1, anscheinend nutzt sparkjava den Support von Jetty für http/2 nicht (?)

Piktogramm schrieb:
Ansonsten, wenn deine Logik vom Server nicht zu groß ist. Wäre es vielleicht auch ein Gedanken wert, ob du dein Backend mittels Node nicht auch in Javascript schreibst.
Könnte man prinzipiell drüber nachdenken, ja. Ich denke aber mangels Erfahrung mit Node und wegen der (hoffentlich) relativ einfachen Umsetzung in java wird es eher dabei bleiben.
 
Zurück
Oben