API-Paginierung mit externer oder zentraler Autorisierung
Ich erstelle eine REST-API, die ein Front-End sowie andere Apps von Drittanbietern mit Strom versorgt, und möchte daher, dass sie so "Standard" wie möglich ist. Im Moment versuche ich, mich an HATEOAS zu halten. Der einzige Ort, an dem ich zu kämpfen habe, ist die Paginierung.
Die Berechtigungsschicht unserer Anwendung ist zentralisiert. Mehrere andere Apps verwenden den zentralisierten Authentifizierungsdienst, daher muss meine API denselben verwenden. Dies führt zu offensichtlichen Problemen bei der Paginierung, nämlich:
- Wie kann ich die Anzahl der Einträge auf eine erforderliche Anzahl beschränken?
- Wie kann ich Einträge einer gültigen Seite zurückgeben?
- Wie kann ich die Gesamtzahl der Seiten zurückgeben?
Im Moment verwende ich eine Ad-hoc-Lösung, die alle Datensätze aus der Datenbank gemäß den API-Filtern und dann der Autorisierungsschicht abruft, die nicht autorisierten Datensätze filtert und dann eine weitere Schicht (nennen wir es die "Paginierungsschicht") gemäß den Seitenparametern.
Dies funktioniert vorerst, da unser Datensatz relativ klein ist, aber ich denke nicht, dass dies gut skaliert. Was sind meine Optionen?
PS Es gibt ein paar Dinge, über die ich nachgedacht habe, aber keine Ahnung habe, wie gut eine Idee ist:
- Das Frontend kann in einen Lazy-Loading-Mechanismus umgeschaltet werden, sodass die Rückgabe genau einer bestimmten Anzahl von Einträgen nicht mehr erforderlich ist. Das Frontend kümmert sich bei Bedarf um die Abfrage der nächsten Seite. Dies wird jedoch Entwicklern von Drittanbietern, die die API verwenden, eine schlechte Erfahrung machen.
- Die Geschäftsschicht erhält nur die Anzahl der Datensätze wie auf der Seite, und die Paginierungsschicht entscheidet, ob mehr Abfragen erforderlich sind, um mehr Daten abzurufen. Dies scheint in vielerlei Hinsicht eine schlechte Idee zu sein, da dies nicht dazu führt, dass eine bestimmte Seite abgerufen wird.
Antworten
Für eine effiziente Lösung müssen Sie in der Lage sein, die Berechtigungs- und Paginierungsbeschränkungen in die Datenbankabfrage aufzunehmen und über die richtigen Indizes für diese Aspekte zu verfügen. Alles andere wird möglicherweise eine enorme Datenmenge überholen. Wie groß das Problem ist, hängt ganz von der Größe und den Eigenschaften Ihrer Daten ab.
Können Sie die Informationen, die Sie von der Berechtigungsschicht erhalten, in einen Filter für die Datenbankabfrage übersetzen? Idealerweise erhalten Sie die Informationen "Benutzer A kann auf die Projekte X, Y und Z zugreifen" und übersetzen diese in Filter für Ihre Abfrage.
Wenn Sie dies nicht tun können und jedes einzelne Ergebnis übergeben müssen, um festzustellen, ob es sichtbar ist, haben Sie immer einige pathologisch langsame Szenarien. Wenn Sie beispielsweise 1 Million Elemente haben und Ihr aktueller Benutzer 10 davon anzeigen darf, müssen Sie möglicherweise die gesamte Million Elemente durch die Berechtigungsschicht schieben, um 10 Ergebnisse zu erhalten. Wie groß das Problem ist, hängt stark von den Besonderheiten Ihrer Anwendung ab.
Wenn Sie nicht alle diese Bedenken in die Datenbank übertragen können, was meiner Beschreibung nach der Fall ist, ist Ihrer Meinung nach so etwas wie Ihre Lösung 2 der einzig vernünftige Weg, um damit umzugehen. Sie benötigen im Wesentlichen eine interne Paginierungsschicht, die eine Reihe von Ergebnissen abruft, diese durch die Berechtigungsschicht leitet und sie dem Rest Ihrer Anwendung zur Verfügung stellt. Ihre extern sichtbare Paginierungsebene muss dann interne Seitenergebnisse anfordern, bis sie ausreicht, um die Anforderung zu erfüllen.
Dies hat das oben erwähnte Problem mit potenziell pathologischen Leistungsabfragen, aber ich sehe keine Möglichkeit, dies mit diesen Einschränkungen zu vermeiden. Es gibt auch kein grundlegendes Problem beim Abfragen bestimmter Seiten auf diese Weise. Es ist nur teuer, da Sie zuvor auch alle Seiten abfragen müssen. Dies ist jedoch ein allgemeines Problem bei der Paginierung, es sei denn, Sie können erweiterte Methoden wie die Keyset-Paginierung verwenden.
Wenn dies möglich ist, können Sie auch einfach vermeiden, bestimmte Seiten abzufragen. Sie würden also in jeder paginierten Antwort nur einen "nächsten" Link angeben. Dies gibt Ihnen die größte Flexibilität beim Entwerfen Ihrer Paginierung, schränkt jedoch offensichtlich die Möglichkeiten des Kunden ein.