# StattBuchung Hilfezentrum : Private API

Created by Thomas Mack on Jul 01, 2017

StattBuchungWeb ist eine Java-Anwendung, die in einem Tomcat Application Server läuft und über einen Apache httpd-Server zur Verfügung gestellt wird. Der Zugang erfolgt ausschließlich über die URI https://stattbuchung.de. Die API ist http(s)-basiert und kann somit (neben Browsern, offensichtlich) von beliebigen Anwendungen aus angesprochen werden. Geeignete open-source-Bibliotheken werden z.B. von der Apache Foundation angeboten.

Die API unterscheidet nicht zwischen verschiedenen Typen von Clients (user agents). Bei einer nicht erfolgreichen Anmeldung z.B. wird der Client an eine URI weitergeleitet, die diesen Umstand erläutert und bedauert. Es ist Aufgabe des Clients, diese Information zu interpretieren. (Allerdings kann genau hierfür auch die Interpretation des http-Status verwendet werden, siehe dazu unten mehr).

### Login und Sessions

Der Zugriff auf die API erfolgt im Rahmen einer Usersession: Anmelden, Session starten, weitere API-Aufrufe, Abmelden. Die Usersession wird http-seitig mit Cookies realisiert, der Client muss also Sessioncookies akzeptieren und verwalten können. Die Anzahl der Usersession ist begrenzt. Im Produktivbetrieb ist nur eine parallele Session erlaubt, während des Testbetriebs deutlich mehr, da es dazu kommen kann, dass ein Clientprogramm sich nicht korrekt abmeldet und damit den Sessioncounter dekrementiert. Alle offenen Sessions werden jede Nacht durch den Server geschlossen. Die Begrenzung der parallelen Sessions ist ein Sicherheitsaspekt und technisch nicht erforderlich, Nebenläufigkeitseffekte sind aber zumindest nicht auszuschließen.

Zugriffsschutz und Authentifizierung werden durch das CMS (Container Managed Security) des Tomcat realisiert. Dieses Verfahren gilt als sehr sicher, erzeugt aber leider auch etwas Aufwand bei der Anmeldung. Nach 3 ungültigen Anmeldeversuchen wird der Account stillschweigend für 30 Minuten gesperrt.

### Container Managed Security

Verkürzt dargestellt wird durch CMS der gesamte Webcontent rollenbasiert verwaltet und nur in authentifizierten Usersessions eingeblendet, die über doe notwendigen Rollen verfügen. Das anfordern einer Seite aus dem Webcontent führt ohne Authentifizierung zur Umleitung des requests auf ein Loginformular. Das direkte Aufrufen des Formulars ist aus Sicherheitsgründen verboten. Nach dem Absenden des Formulars und erfolgreicher Prüfung der Credentials und der Rollen wird über den http-Status 302 angezeigt, dass der Webcontent zur Verfügung steht, ansonsten wird der Status 200 zu-rückgegeben. Danach muss mit einem weiteren http-Request die logische Session eröffnet werden, so dass der Login-Vorgang also aus 3 http-Requests besteht.

### Requests und URI

Die http-Requests werden von einem Frontcontroller entgegengenommen, bearbeitet und retourniert. Die Struktur der requests, also die eigentliche URI, besteht aus

- Schema,
- FQDN,
- Port,
- Verzeichnis,
- Frontcontroller,
- optional gefolgt von Parametern. Im konkreten Anwendungsfall

Also z.B. `https://stattbuchung.de:443/SDW/statt/fc?opc=1002`

Um die API unabhängig vom Typ des requests (post/get) zu machen werden alle Parameter in der Form param=value erwartet, sowohl in der URI `...?param1=value1&param2=value2...`

als auch im Postbody. Der Postbody enthält also also die Zuweisung `JSON=MySerializedJSONObject`

enthalten.

Die Verbindung ist zwar SSL verschlüsselt, so dass auch die URI selbst verschlüsselt ist, trotzdem sollte man bedenken dass die URI abhängig vom verwendeten Client angezeigt oder historisiert wird, so dass sensible Daten nicht als URI-Parameter übergeben sondern im Postbody versendet werden sollten. Weiterhin sind Längenbeschränkungen und Encodingprobleme zu berücksichtigen. Als Faustregel gilt deshalb, dass Nutzlasten immer im Postbody versendet werden sollten, andere requests (logon, logoff, getPDF,...) können als get request formuliert werden.

Die Kodierung ist immer UTF-8.

Grundsätzlich sollte immer nur ein Aufruf zu einer Zeit erfolgen. Technisch ist das natürlich keine Einschränkung, der Frontcontroller skaliert hervorragend, und auch auf Objektebene gibt es keine Nebenläufigkeitsprobleme, da jedes Objekt nur einmal im Hauptspeicher des Application Servers vorhanden ist. Änderungen werden im Rahmen eines Monitors sofort persistent gemacht. Allerdings ist es relativ aufwendig, clientseitig die Zugriffe so zu synchronisieren, das sie innerhalb einer Session laufen und diese erst am Ende des letzten Zugriffs geschlossen wird.

### Parameter

Jeder request darf jeden Parameter nur maximal einmal enthalten, bei Doppelungen ist nicht vorhersehbar, welche Instanz verwendet wird. Jeder request muss den Opcode-Parameter `opc=MyOpcode` enthalten. Der Opcode wird im Frontcontroller dispatcht und definiert den Zweck des requests. Aus Sicherheitsgründen ist der Opcode eine UUID, so wird potentiellen Angreifern das Ausprobieren von Opcodes –nun- erschwert. Das Fehlen des Opcodes sowie die Übergabe eines invaliden Opcodes führt zu einer WrongParamException. Es hat sich eingebürgert den Opcode in der URI zu übergeben und nicht im Postbody, aber grundsätzlich ist das wahlfrei. Weitere Parameter werden kontextabhängig definiert. Komplexere Attributierungen, z.B. die queryoptions für die Suche nach Buchungen, werden als JSON-Objekt formuliert (Parameter JSON=) im Postbody.

### Nutzlast

Alle zu übertragenden Objekte müssen serialisierte JSON-Objekte sein.

### Response

Der Frontcontroller retourniert ein serialisiertes JSON-Objekt als Antwort. Der verwendete Opcode bestimmt, welches JSON-Objekt zurückgegeben wird.