Unsere Datenschutzrichtlinie wird in Kürze aktualisiert. Bitte sehen Sie sich die Vorschau an.

Java EE 7: Web Services

RESTful Services absichern

Testen Sie unsere 2014 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Manchmal sollen RESTful Services nicht jedem Client zugänglich sein oder sind, wenn auf anderen Servern, nicht jeder JavaScript-Applikation zugänglich. Dieses Video verrät die Lösung dieser Probleme.

Transkript

Der Zugriff auf RESTful Services soll üblicherweise nicht uneingeschränkt erfolgen, sondern man möchte sehr häufig dafür sorgen, dass nur bestimmte Applikationen, vielleicht sogar nur bestimmte Versionen bestimmter Applikationen auf eine Applikation und deren RESTful Services zugreifen dürfen. In diesem Video werden wir uns damit auseinandersetzen. Wir werden klären, welche Ansätze es gibt. Und wir werden betrachten, wo das Problem beim Zugriff auf RESTful Services aus JavaScript-Sicht liegt und wie wir diesem Problem beikommen können. Generell ist es so, dass für die Absicherung von RESTful Services keine Standards existieren. Es ist so, weil RESTful Services selbst auch keinem Standard unterliegen, sondern nur eine Konvention sind. Üblicherweise unterscheidet man allerdings schon zwei Ideen, die man umsetzen kann. Zum einen die Absicherung auf Containerebene, per Basic Authentication oder Ähnlichem. Und zum anderen die Absicherung auf der Applikationsebene, wo zum Beispiel Header-Werte ausgewertet werden. Die Absicherung auf Containerebene besagt, dass die Sicherheit bereits auf Ebene des Servers gewährleistet wird. Dazu werden Benutzer und Rollen hinterlegt. Diese Benutzer und Rollen werden dann mit Standardmechanismen überprüft. Nur wenn Benutzer und Rollen zusammenpassen und Benutzern und Rollen der Zugriff auf die Applikation gewährleistet ist, darf auf die Applikation wirklich zugegriffen werden. Solange bekommt die Applikation auch gar nichts davon mit. Die Konfiguration dieses Ansatzes findet in web.xml statt. Das bedeutet auch, dass der Client entsprechend konfiguriert sein muss und die entsprechenden Authentifizierungs- informationen übertragen muss. Die Absicherung auf Containerebenen ist für RESTful Services nicht sonderlich üblich. Viel häufiger trifft man hier auf die Absicherung auf Applikationsebene. Dabei wird die Sicherheit in der Applikation selbst gewährleistet. Denn von außen ist ein Zugriff auf den Service jederzeit möglich. Üblicherweise werden hier Header-Werte eingesetzt. Das bedeutet, es gibt zusätzliche HTTP-Header, die dann ausgewertet werden. Die Applikation sorgt für diese Auswertung in aller Regel per Interceptor. Interceptor ist eine Technologie, die mit Java EE 7 und JAX-RS 2.0 eingeführt worden ist, und sie erlaubt, zusätzliche Funktionalitäten bereitzustellen, ohne dass der eigentliche RESTful Service in irgendeiner Art davon betroffen ist. Wir können mit Interceptors eingehende und ausgehende Anforderungen überprüfen und manipulieren. Im JavaScript-Umfeld sieht das Problem genau andersrum aus. Da ist es so, dass die JavaScript-Applikation sehr gern auf fremde Server zugreifen möchte, zum Beispiel auf einen Service, der von Google bereitgestellt worden ist. Bei Google ist das wiederum kein Problem. Aber wenn Sie nicht Google sind, ist das ein echtes Problem. Denn die Same Origin Policy (SOP) verbietet den Zugriff auf fremde Server. Das ist fest eingebaut in die Browser und stellt für den normalen Web-Entwickler ein unüberwindliches Hindernis dar. Das heißt, seine Web-Applikation darf nicht auf fremde Server zugreifen. Der Hintergrund ist ein Sicherheitsgedanke. Nur bei RESTful Services will man diesen Sicherheitsgedanken eigentlich nicht haben, wenn man diesen Service übergreifend zur Verfügung stellen möchte. Die Lösung besteht darin, das sogenannte Cross Origin Resource Sharing (CORS) zu aktivieren. Das geschieht in der Regel darüber, dass Header-Werte gesetzt werden. Dabei wird zumindest der Access-Control- Allow-Origin-Header benötigt. Damit kann ich angeben, von welchen Servern aus der Zugriff erlaubt ist. JavaScript wertet das aus und dann wird entsprechend auf die Applikation zugegriffen oder es ist weiterhin nicht möglich, wenn der entsprechende fremde Server nicht in diesem Header erwähnt ist. Auch das wird üblicherweise per Interceptor implementiert. Lassen Sie uns nun einen Blick darauf werfen, wie wir Interceptors in JAX-RS implementieren können. Wir werden zwei Interceptors implementieren. Ein Interceptor wird eingehend funktionieren und auf einen bestimmten Header überprüfen. Ist der nicht vorhanden, wird eine entsprechende Fehlermeldung generiert. Und der andere Interceptor wird ausgehend funktionieren und die Cross-Origin- Recource-Sharing-Header hinzufügen. Lassen Sie uns zuerst über diesen RESTful Service reden. Dieser RESTful Service ist fertig implementiert, stellt mehrere Methoden bereit, und ist gerade, Status quo, von jedem fremden Server direkt abrufbar, es sei denn der Abruf erfolgt per JavaScript. Grund dafür ist zum einen, dass wir keinerlei Sicherung eingebaut haben, die den Abruf auf irgendeine Art reglementiert, und zum anderen werden die CORS-Header nicht gesetzt. Das wollen wir nun ändern. Lassen Sie uns davor aber kurz im Fiddler Tool schauen, was wir bekommen, wenn wir auf diesen Service zugreifen, und was wir nicht bekommen. Hier im Fiddler Tool rufe ich nun eine Methode dieses RESTful Service auf. Sie sehen, der Zugriff klappt problemlos. Die Rückgabe hat den Status quo 200. Und wenn wir uns das anschauen, wir bekommen hier einige Header zurück, von denen aber keiner einem CORS-Header entspricht. Das heißt, beide Dinge, die wir implementieren wollen, existieren hier noch nicht. Aus diesem Grund werden wir nun zuerst einen Interceptor implementieren, der es uns erlaubt, die eingehende Anforderung zu unterbrechen. Wir legen dazu eine neue Klasse an. Diese Klasse nennt sich AuthInterceptor. Sie befindet sich im Package de.video2brain.services.interceptors. So ein Interceptor verfügt immer über die @Provider-Annotation und kann PreMatching oder PostMatching eingestellt sein. PreMatching heißt, er schlägt zu, bevor eine Verarbeitung stattfindet, und PostMatching nachdem. Wir markieren diesen Interceptor als PreMatching. Darüber hinaus implementieren das Interface ContainerRequestFilter, um damit anzudeuten, dass wir eingehende Requests verarbeiten. Dieses Interface erfordert, dass wir eine Methode filter implementieren. Hier ändere ich den automatisch generierten Parameternamen. Nun können wir in dieser Methode versuchen, unsere Sicherheit zu implementieren. Die Sicherheit implementieren wir, indem wir einen X-AUTH header erwarten. Der soll einen bestimmten Wert haben, nämlich sicher!. Auf diesen Header greifen wir zu und lesen dessen Wert in eine Zeichenkette ein. Der Zugriff erfolgt über ContainerRequestContext und dessen Methode getHeaderString. Hier geben wir den Header-Namen einfach an. Existiert diese Header nicht, wird headerValue den Wert null haben. Ansonsten steht der Wert des Headers dann in unserer Variable. Jetzt können wir darauf überprüfen. Wenn headerValue == null ist, oder headerValue nicht den Wert sicher! hat, dann ist die aktuelle Anforderung abzubrechen. Dies machen wir, indem einen ResponseBuilder benutzen. Den lassen wir erzeugen über die statische Methode status der Response-Klasse. Hier können wir vorgefertigte Statuswerte benutzen. Die befinden sich in dieser Response-Klasse beziehungsweise -Auflistung. Wir verwenden hier den Status-Code EXPECTATION_FAILED, weil eine Anforderung beziehungsweise eine Erwartung fehlgeschlagen ist. Den ResponseBuilder verwenden wir nun, um eine Response-Instanz zu erzeugen. Das machen wir über dessen Methode build. Zuletzt beenden wir die Verarbeitung über die Methode abortWith und übergeben dort die neu generierte Rückgabe. Damit ist dieser Interceptor schon einsatzbereit. Wir werden ihn nun auf dem Server deployen. Nach wenigen Sekunden ist unsere Applikation neu deployed und der Interceptor scharf geschaltet. Zurück im Fiddler Tool versuche ich erneut, die Anforderung an den Server zu senden. Wir sehen, es gibt nun eine Rückgabe mit dem Statuscode 417, Expectation Failed. Das ist genau das, was wir implementiert haben. Lassen Sie uns nun den X-AUTH Header hinzufügen und dort den Wert sicher! übergeben. Nun wird die Anforderung wie gehabt erfolgreich ausgeführt werden. Im Folgenden werden wir noch einen zweiten Interceptor implementieren. Dieser Interceptor wird ausgehend funktionieren und die für den Cross-Origin-Zugriff benötigten Header der Rückgabe hinzufügen. Dazu legen wir im selben Package einen weiteren Interceptor an. Den nennen wir CorsInterceptor. Auch dieser Interceptor ist ein Provider. Und auch er ist PreMatching ausgeführt. Das steht nicht im Widerspruch dazu, dass er eigentlich erst zuschlagen soll, nachdem die Anforderung verarbeitet wird. Sondern es geht an der Stelle einfach nur darum: Wann wird er ausgeführt? Vor anderen oder nach anderen Interceptors? Vor Infrastruktur- oder nach Infrastrukturaufgaben? Er implementiert diesmal die Schnittstelle ContainerResponseFilter. Auch diese Schnittstelle erfordert, dass wir eine Methode implementieren. Diese verfügt diesmal über zwei Parameter, nämlich einmal ContainerRequestContext und einmal ContainerResponseContext. Hier fügen wir dem ReponseContext über dessen getHeaders-Auflistung Header entsprechend hinzu, und zwar Access-Control-Allow-Origin, mit entweder der Angabe von Domain-Namen oder einem Stern. Damit erlauben wir alle externen Domains. Wir fügen auch einen weiteren Header hinzu, nämlich Access-Control-Allow-Methods. Damit schränken wir ein, welche Methoden erlaubt sind. GET, POST, DELETE, und PUT sind gestattet. Alle anderen HTTP-Methoden sind verboten. Damit ist dieser Interceptor auch fertig implementiert und wir können ihn scharf schalten, indem wir die Applikation neu deployen. Im Fiddler Tool können wir nun die Anforderung erneut ausführen. Und werden in der Rückgabe die zusätzlichen Header vorfinden können. Access-Control-Allow-Methods und Access-Control-Allow-Origin. Auch dies war mit sehr wenig Aufwand möglich. Und nun ist es möglich, dass JavaScript-Applikationen, die irgendwo im Internet liegen, auf unseren RESTful Service zugreifen können. In diesem Video haben wir uns damit auseinandergesetzt, wie wir RESTful Services zum einen absichern können, und wie wir zum anderen JavaScript-basierten Applikationen den Zugriff erlauben können, auch wenn sie sich auf anderen Servern befinden. Beide Ansätze wurden mit sogenannten Interceptors umgesetzt.

Java EE 7: Web Services

Steigen Sie ein in die Java-Enterprise-Welt und lernen Sie, wie Nachrichten ausgetauscht und Dienste definiert werden.

5 Std. 13 min (30 Videos)
Derzeit sind keine Feedbacks vorhanden...
 

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!