Du hast deinen AdBlocker an?

Es wäre ein Traum, wenn du ihn für t3n.de deaktivierst. Wir zeigen dir gerne, wie das geht. Und natürlich erklären wir dir auch, warum uns das so wichtig ist. Digitales High-five, deine t3n-Redaktion

t3n 17

REST-basierte Schnittstellen mit dem Symfony-Framework implementieren: Web Services leicht gemacht

Im Web 2.0 verfügen praktisch alle großen Anbieter über eine API. Application Programming Interfaces ermöglichen anderen Applikationen den kontrollierten Zugang zu den eigenen Daten und bilden so die Grundlage für Mash-Ups oder Third-Party-Applikationen. Das PHP-basierte MVC-Framework Symfony macht es einfach, derartige Schnittstellen effizient und sauber zu entwickeln. Dieser Artikel beleuchtet den Aufbau von solchen Application Programming Interfaces und demonstriert, wie sie sich mit Hilfe des Symfony-Frameworks implementieren lassen.

REST-basierte APIs spielen in den letzten Jahren eine immer wichtigere Rolle im Web 2.0. Mit Hilfe einer derartigen Schnittstelle können Anbieter von Webdiensten anderen Anwendungen Daten in kontrolliertem Umfang bereit stellen und sich auf diese Weise Zielgruppen jenseits der eigenen Website erschließen. APIs sind so zu einem sehr wichtigen Erfolgsfaktor geworden – man denke nur an Twitter oder Facebook und deren Ökosystem von Third-Party-Applikationen.

Mit Hilfe des Symfony-Frameworks [1] lassen sich derartige APIs auf Basis von REST [2] sehr effektiv umsetzen. Dies lässt sich am besten anhand eines beispielhaften Anwendungsfalls verdeutlichen: Ein fiktiver Buchhändler stellt eine Schnittstelle bereit, über den sich Informationen zum Angebot abfragen lassen und mit der Verleger mit Hilfe eines dedizierten Clients neue Bücher direkt in der Datenbank des Händlers speichern können.

Die Grundlagen von REST

Eine REST-basierte Schnittstelle besteht aus Ressourcen, die durch URIs adressierbar sind und in verschiedenen Repräsentationen dargestellt werden können. Ressourcen sind Informationen, die eigenständig referenziert werden sollen, beispielsweise Texte, ein Benutzerprofil oder eine Suchergebnisseite. Deren Repräsentation erfolgt meistens im XML-Format, da dieses Format die gewünschte Interoperabilität zwischen verschiedenen Systemen oder Plattformen noch am besten sicherstellen kann. Andere Formate wie JSON sind aber ebenfalls denkbar. Ressourcen lassen sich, wie auch im Web, miteinander verlinken.

Der Zugriff auf die API erfolgt ganz einfach durch das HTTP-Protokoll. Die verschiedenen Methoden des Protokolls codieren die Operationen auf der Anwendungsebene. Wird beispielsweise per GET auf eine Ressource zugegriffen, weiß der Server, dass ein Lesevorgang durchgeführt werden soll – derselbe Request mit der DELETE-Methode würde die Ressource hingegen löschen (mehr dazu unter [3] ).

Tools zum Testen von REST-APIs
REST-basierte Schnittstellen lassen sich nicht direkt im Browser entwickeln oder testen, da sich die HTTP-Methoden für den Request nicht festlegen lassen und auch kein direkter Zugriff auf weitere Parameter des HTTP-Requests besteht. Abhilfe schafft das Programm „RESTClient“ (http://bit.ly/RESTClient) oder die Firefox-Erweiterung „RestTest“ (http://bit.ly/RESTTest).

Symfony ist modular aufgebaut, einzelne Komponenten lassen sich auch eigenständig verwenden.
Symfony ist modular aufgebaut, einzelne Komponenten lassen sich auch eigenständig verwenden.

Bitte beachte unsere Community-Richtlinien

6 Reaktionen
Daniel Haller

Freut mich zu hören, Dankeschön :)

fishbone

Auf jeden Fall danke ich für den Artikel, der mich bei diesem Projekt, das inzwischen abgeschlossen ist, sehr unterstützt hat.

Daniel Haller

Ja, da hast Du recht - die Version 1.x von symfony ist noch nicht so 100%ig RESTfull wie das bspw. bei Rails der Fall ist. Ich kam leider noch nicht dazu, mich mit 2.x auseinander zu setzen, aber soweit ich bisher gelesen habe, wird hier sehr viel stärker auf eine RESTartige Architektur gesetzt. Ich würde mich wundern, wenn im Rahmen dessen nicht auch eine Authentifizierungslösung integriert wärde.

Ein leeres API-Key Feld darf aber natürlich nicht sein wenn man eine Schnittstelle implementiert, das ist klar. Ich bin in meinem Fall davon ausgegangen, dass es sich schon auf DB-Ebene um ein NOT NULL-Feld handelt, dass in jedem Fall befüllt sein muss - vielleicht hätte ich in dem Artikel noch darauf hinweisen sollen.

fishbone

Wie bereits gesagt, entsteht das Problem nur, falls das ApiKey-Feld in der Tabelle für einen Benutzer leer ist. Wenn kein Api-Key bei der Authentifizierung übergeben wird, stimmen die ApiKeys überein (übergebener und leerer in der Datenbank).

Es ist klar, dass dies ein grundlegender Fehler ist. Die Spalte Api-Key darf natürlich nicht leer oder NULL sein. Allerdings kann dies passieren, wenn man die Schnittstelle erst in einer späteren Version hinzufügt und bereits Benutzerdaten vorhanden sind. Bei der Migration kann durchaus ein Fehler entstehen, der ein leerbleibendes ApiKey-Feld zur Folge hat. Auch wenn das unwahrscheinlich ist, möglich ist es.

Deswegen leite ich in meinem sfFilter sofort zu 401 weiter, falls kein ApiKey übergeben worden ist. Ich weiß aber nicht mehr, wie ich das im Detail gelöst habe. Denn wenn sich jemand über Cookie authentifiziert, wird (korrekterweise) auch kein ApiKey übergeben.

Zum Thema saubere Lösung:
Schnittstellen sind kein Sonderfall. Trotzdem muss man sich mit dem Aufbau des Sicherheitssystem befassen, während man für die normale Authentifizierung auf die offiziellen Symfonyplugins zurückgreifen kann. Vielleicht hätte ich da von Symfony einfach mehr erwartet. Aber schon Methoden wie forward404If() zeigen, dass Symfony 1 nicht unbedingt für REST ausgelegt ist.

Daniel Haller

Hallo fishbone,

glaube, so ganz verstehe ich Dein Problem nicht. Zugriffe mit ungültigen API-Keys werden mit einem Fehler 401 geblockt. Natürlich sollte man die Keys so aufbauen, dass sie nicht erraten werden können und eine SSL-gesicherte Verbindung verwenden.

Wenn ich Dich richtig verstanden habe, hast Du aber mit einem anderen Anwendungsfall Bauchschmerzen: Ein User könnte sich gegenüber der API mit einem korrekten Key authentifizieren und anschließend auf Datensätze zugreifen, die nicht von ihm selbst stammen. Habe ich das richtig verstanden? Das wäre allerdings keine Lücke, die man auf Ebene der API lösen kann - dasselbe Problem hätte man schließlich auch bei einer "herkömmlichen" Authentifizierung.
Natürlich muss man auf Applikationsebene sicherstellen, das ein bereits authentifizierter User (egal ob er sich mit einem API-Key oder Name/Passwort-Kombination authentfiziert hat) auch nur auf seine eigenen Datensätze zugreifen kann - auch dann wenn die Datensätze fehlerhaft in der DB abgelegt wurden (was ja schon an der Stelle verhindert werden müßte).

Hilft Dir das weiter? Oder habe ich Dich missverstanden?

vg,
Daniel

fishbone

Mit der Api-Key Lösung durch einen Filter entsteht das Problem, dass jeder vollen Zugriff hat, sobald z.B. aufgrund eines Fehlers ein Record erzeugt wurde der keinen Api-Key enthält.

Im Allgemeinen suche ich eine saubere Lösung für das Authentifizierungsproblem für Webservices in Symfony. Das wird im Jobeet-Tutorial geschickt übergangen, weil es in dem verwendeten Beispiel aufgrund des reinen Lesezugriffs nicht erforderlich ist. Um das Sessionbasierte Sicherheitssystem hinreichend anzupassen, bin ich jetzt seit Tagen damit beschäftigt, den kompletten Aufbau von Symfony zu analyisieren.
Dabei kommt mir immer wieder in den Sinn, dass es dafür bereits fertige saubere Lösungen geben müsste.
Vor allem denke ich, dass in puncto Sicherheit generell keine Workarounds angebracht sind.

Du musst angemeldet sein, um einen Kommentar schreiben zu können.

Jetzt anmelden

Finde einen Job, den du liebst