Überblick:
Mein Unternehmen hat eine ratenbegrenzte API entwickelt. Unser Ziel ist zweierlei:
- A: Erstellen Sie ein starkes Entwickler-Ökosystem rund um unser Produkt.
- B: Demonstrieren Sie die Leistungsfähigkeit unserer API, indem Sie damit unsere eigene Anwendung steuern.
Klarstellung: Warum überhaupt ein Ratenlimit?
Wir begrenzen unsere API, weil wir sie als Ergänzung zu unserem Produkt verkaufen. Der anonyme Zugriff auf unsere API hat einen sehr niedrigen Schwellenwert für API-Aufrufe pro Stunde, während unseren bezahlten Kunden mehr als 1000 Anrufe pro Stunde oder mehr gestattet sind.
Das Problem:
Unsere ratenbegrenzte API eignet sich hervorragend für das Entwickler-Ökosystem, aber damit wir sie mit Hundefutter füttern können, können wir nicht zulassen, dass sie auf dieselbe ratenbegrenzte API beschränkt wird. Das Front-End unserer API besteht ausschließlich aus JavaScript und führt direkte Ajax-Aufrufe an die API durch.
Die Frage ist also:
Wie sichern Sie eine API, damit die Ratenbegrenzung entfernt werden kann, während das Entfernen einer solchen Ratenbegrenzung nicht einfach gefälscht werden kann?
Explored Solutions (und warum sie nicht funktionierten)
Überprüfen Sie den Referrer anhand des Host-Headers. - Fehlerhaft, da der Überweiser leicht gefälscht werden kann.
Verwenden Sie eine HMAC , um eine Signatur basierend auf der Anforderung und einem gemeinsamen Geheimnis zu erstellen, und überprüfen Sie dann die Anforderung auf dem Server. - Fehlerhaft, da das Geheimnis und der Algorithmus leicht durch einen Blick in das Front-End-JavaScript ermittelt werden können.
Proxy der Anfrage und Signieren der Anfrage im Proxy - Immer noch fehlerhaft, da der Proxy selbst die API verfügbar macht.
Die Frage:
Ich freue mich auf die brillanten Köpfe von Stack Overflow, um alternative Lösungen vorzustellen. Wie würden Sie dieses Problem lösen?
quelle
Antworten:
Da Ihr eigener JavaScript-Client direkt auf die API zugreift, kann jeder sehen, was er tut, und es nachahmen, einschließlich der Verwendung des gleichen API-Schlüssels. Sie können versuchen, es schwieriger zu machen, indem Sie beispielsweise Ihren Code verschleiern oder verschiedene Hürden in den Weg stellen, aber Sie und die Person, die Sie zurückhalten möchten, haben grundsätzlich denselben Zugriff. Anstatt zu versuchen, einen Unterschied in den Berechtigungen zu schaffen, müssen Sie ein System erstellen, in dem es völlig in Ordnung ist, dass der inoffizielle Client den gesamten Zugriff in seinem Umfang verwendet, das System jedoch so angeordnet ist, dass die offizielle Verwendung für alle Clients erfolgt größer.
Dies erfolgt häufig mit Zugriffstoken pro Benutzer im Gegensatz zu einem Token für die gesamte Anwendung. Das Limit jedes Tokens sollte für die typische Verwendung Ihrer API ausreichend sein, für jemanden, der versucht, es zu missbrauchen, jedoch einschränkend sein. Zum Beispiel könnten 100 Anrufe pro Minute mehr als genug sein, um das typische Surfen zu unterstützen, aber wenn ich Sie kratzen möchte, kann ich es mit diesem Budget nicht effektiv machen.
Es wird immer ein Wettrüsten geben - ich kann das Limit umgehen, indem ich viele Bot-Benutzerkonten erstelle. Dies ist jedoch ein ziemlich gelöstes Problem, wenn Sie Ihrem Anmeldefluss nur ein Captcha hinzufügen, und dies mit einem winzigen Aufwand für den echten Menschen. Wenn Sie in diese Szenarien einsteigen, ist alles nur ein Kompromiss zwischen Bequemlichkeit und Einschränkung. Sie werden nie etwas finden, das absolut kugelsicher ist. Konzentrieren Sie sich also darauf, es gut genug zu machen, und warten Sie, bis Sie jemand ausnutzt, um herauszufinden, wo die Löcher waren.
quelle
Wenn dies zu einem Problem führt, verursacht Ihr mutmaßliches Ökosystem von Entwicklern ein Problem (z. B. wenn sie versuchen, eine alternative Benutzeroberfläche zu entwickeln). Wenn Sie wirklich Ihr eigenes Hundefutter essen, lassen Sie die API (und die Ratenbegrenzung) für Ihre Anwendung funktionieren. Hier sind ein paar Vorschläge:
Ratenlimit nicht nach IP-Adresse. Ratenbegrenzung durch etwas, das dem Benutzer zugeordnet ist, z. B. seine Benutzer-ID. Wenden Sie das Ratenlimit in der Authentifizierungsphase an.
Entwerfen Sie Ihre API so, dass Benutzer sie nicht kontinuierlich aufrufen müssen (z. B. einen Listenaufruf, der viele Ergebnisse zurückgibt, anstatt einen wiederholten Aufruf, der jedes Mal ein Element zurückgibt).
Entwerfen Sie Ihre Web-App mit denselben Einschränkungen, die Sie von Ihrem Entwickler-Ökosystem erwarten, dh stellen Sie sicher, dass Sie sie mit angemessenen Drosselungsraten entwerfen können.
Stellen Sie sicher, dass Ihr Back-End skalierbar ist (vorzugsweise horizontal), damit Sie keine Drosselung bei so niedrigen Pegeln vornehmen müssen, dass eine Benutzeroberfläche tatsächlich Probleme bekommt.
Stellen Sie sicher, dass Ihre Drosselung in der Lage ist, mit Ausbrüchen umzugehen und längerfristigen Missbrauch zu begrenzen.
Stellen Sie sicher, dass Ihre Drosselung sinnvolle Aktionen ausführt, die auf den Missbrauch zugeschnitten sind, den Sie beseitigen möchten. Ziehen Sie beispielsweise in Betracht, milde Missbraucher in die Warteschlange zu stellen oder zu verzögern, anstatt die Verbindung abzulehnen. Die meisten Web-Frontends öffnen nur vier gleichzeitige Verbindungen gleichzeitig. Wenn Sie einen Versuch, ein Fünftel zu öffnen, verzögern, werden Sie nur dann auftreten, wenn sie gleichzeitig mit dem Webclient (oder zwei Webclients) eine CLI verwenden. Wenn Sie den n-ten API-Aufruf ohne Lücke verzögern, anstatt ihn fehlzuschlagen, wird der Endbenutzer feststellen, dass die Dinge eher langsamer als unterbrochen werden. Wenn Sie dies mit der gleichzeitigen Warteschlange von N API-Aufrufen kombinieren, werden Sie nur Personen treffen, die eine große Anzahl von API-Aufrufen parallelisieren. Dies ist wahrscheinlich nicht das gewünschte Verhalten - z. B. 100 gleichzeitige API-Aufrufe, dann ist eine Lücke für eine Stunde normalerweise weit Schlimmer als 100 sequentielle API-Aufrufe über eine Stunde.
Hat dies Ihre Frage nicht beantwortet? Wenn Sie wirklich das tun müssen , was Sie verlangen, begrenzen Sie die Rate in der Authentifizierungsphase und wenden Sie eine andere Rate an, die auf der Gruppe basiert, in die Ihr Benutzer passt. Wenn Sie einen Satz von Anmeldeinformationen verwenden (die von Ihren Entwicklern und dem QA-Team verwendet werden), erhalten Sie ein höheres Ratenlimit. Sie können jedoch sofort erkennen, warum dies zwangsläufig dazu führt, dass Ihr Ökosystem Probleme sieht, die Ihr Entwickler und Ihr QA-Team nicht sehen.
quelle
Kaufen Sie Ihr Produkt. Werden Sie ein bezahlter Kunde von sich.
"Der anonyme Zugriff auf unsere API hat einen sehr niedrigen Schwellenwert für API-Aufrufe pro Stunde, während unseren bezahlten Kunden mehr als 1000 Anrufe pro Stunde oder mehr gestattet sind."
Dies hilft auch, das System aus Kundensicht zu testen.
quelle
Leider gibt es dafür keine perfekte Lösung.
Der allgemeine Ansatz besteht typischerweise darin, eine Spoofable bereitzustellenMöglichkeit für Clients, sich zu identifizieren (z. B. eine Kennung, eine Version und ein API-Schlüssel - zum Beispiel), für Clients, Informationen über sich selbst zu registrieren, die zur Einschränkung des Zugriffs verwendet werden können (z. B. der Client ist ein Server in einem bestimmten IP-Adressbereich). Erlauben Sie daher nur Anrufern in diesem Bereich, z. B. dass der Client JavaScript ist, aber nur an eine bestimmte Kategorie von Browsern geliefert wird. Erlauben Sie daher nur den Zugriff auf HTTP-Anforderungen, die bestimmte Zeichenfolgen für Benutzeragenten angeben (usw.), und verwenden Sie dann maschinelles Lernen / Muster Erkennung, um eine anomale Nutzung zu erkennen, bei der es sich wahrscheinlich um einen gefälschten Client handelt, und um dann den Datenverkehr von diesen gefälschten Clients abzulehnen (oder mit Clients zu bestätigen, dass diese Verwendungen tatsächlich nicht vom legitimen Client stammen, ersetzen Sie ihre fälschbaren Anmeldeinformationen und lassen Sie dann weiteren Datenverkehr mit dem älteren nicht zu gefälschte Anmeldeinformationen).
Sie können das Parodieren etwas erschweren, indem Sie mehrere Schlüsselebenen verwenden. Beispielsweise geben Sie einen längerlebigen Berechtigungsnachweis aus, der sich auf einem Server befindet (und der nur in einem begrenzten Satz von IP-Adressbereichen verwendet werden kann), um einen API-Aufruf durchzuführen, der Informationen über den Client (z. B. den Benutzeragenten) und aufzeichnet Gibt einen kurzlebigen clientseitigen Schlüssel zurück, der in JavaScript zur Verwendung auf dem Client für clientseitige API-Anforderungen syndiziert ist. Auch dies ist unvollständig (ein Spoofer könnte denselben Serveraufruf ausgeben, um die Anmeldeinformationen abzurufen), aber es wird schwieriger, wenn der zurückgegebene API-Schlüssel in verschleiertem (und häufig wechselndem) JavaScript oder HTML enthalten ist (was es schwierig machen würde) zuverlässig aus der Antwort zu extrahieren). Dies bietet auch eine Möglichkeit, Spoofing leichter zu erkennen. Der clientseitige Schlüssel ist jetzt an einen bestimmten Client gebunden (z
quelle
Angenommen, die betreffende App muss öffentlich geöffnet sein, haben Sie keine große Auswahl:
Wählen Sie einen anderen Weg, um die Leistungsfähigkeit Ihrer API zu demonstrieren. Schreiben Sie beispielsweise eine solche App und geben Sie ihre Quelle frei, führen Sie diesen Code jedoch nicht aus. Stellen Sie jedoch sicher, dass es gut dokumentiert ist, damit jeder es bereitstellen und sehen kann, dass es funktioniert (vorbehaltlich Drosselung).
Die App, die Sie ausführen, muss überarbeitet werden, um clientseitige API-Anforderungen zu vermeiden und stärker vom Server gerendert zu werden. Sie können Ihre API weiterhin mit Hundefutter versorgen, jedoch nicht auf offensichtliche Weise. Stellen Sie vom Server aus sichere Anforderungen an die drosselfreie API.
Passen Sie die Ratenbegrenzung an, damit Ihre App funktioniert, und investieren Sie in die Leistungsoptimierung, um die Last zu bewältigen.
Und ja, haben Sie die Kern-API in erster Linie drosselfrei und bewahren Sie sie in einem privaten Netzwerk auf. Gas in einer separaten öffentlich zugänglichen Schicht.
quelle
Können Sie eine separate Instanz der Benutzeroberfläche und der drosselfreien API einrichten und dann den Zugriff auf IP-Adressen beschränken, die von Ihrer Organisation stammen?
Stellen Sie beispielsweise das Ganze hinter Ihrer Unternehmensfirewall bereit und hängen Sie die Anwendung an dieselbe Datenbank wie die öffentlich zugängliche Instanz an, wenn Sie Daten zwischen Instanzen austauschen müssen.
quelle
Sie können versuchen, eine eindeutige Sitzungs-ID zu generieren, die an eine bestimmte IP-Adresse / einen bestimmten Benutzer gebunden ist und nur eine begrenzte Lebensdauer hat. Wenn ein Benutzer Ihren Anwendungs-Frontend-JavaScript-Code herunterlädt, fügen Sie die generierte Sitzungs-ID in den JavaScript-Quellcode ein. Die Sitzungs-ID wird an jede Anforderung an Ihre API angehängt und das Ratenlimit wird aufgehoben.
Die ID kann nicht einfach zum Spoofing kopiert werden, da sie nur für eine einzelne IP-Adresse, einen Benutzer und eine begrenzte Zeit gültig ist. Ein Gegner müsste also Ihre Seite aufrufen und den Schlüssel aus Ihrer JavaScript-Quelle herausfiltern oder die Ajax-Anforderung jedes Mal abfangen, wenn ein neuer Benutzer sie verwenden möchte.
Andere Option:
Richten Sie einen Proxy für Ihre eigene Anwendung ein und verwenden Sie die Verschleierung. Die Ajax-Anforderungen an den Proxy verwenden andere Namen als die tatsächlichen API-Aufrufe, und der Proxy übersetzt sie zurück. Ihre Anwendung würde also nicht
getDocument
Ihre echte API aufrufen, sonderngetFELSUFDSKJE
Ihren Proxy. Der Proxy übersetzt diesen Rückruf zurück in getDocument und leitet ihn an die tatsächliche ratenbegrenzte API weiter.Ihre tatsächliche API begrenzt die Anforderungen des Proxys nicht auf die Rate.
Und damit andere Personen Ihren Proxy nicht für ihre eigene Anwendung verwenden, ändern Sie das Verschleierungsschema täglich. Die verschleierten Anrufnamen können automatisch in Ihrem JavaScript-Quellcode generiert und im Proxy konfiguriert werden.
Ein Client, der dies verwenden möchte, muss auch mit Ihrer sich ändernden Verschleierung Schritt halten, um Ihren Proxy verwenden zu können. Sie können weiterhin Referrer-Header und ähnliches für die Protokollierung verwenden, sodass Sie Personen finden können, die Ihren Proxy verwenden. Oder fangen Sie sie, wenn Sie das Verschleierungsschema ändern.
quelle
quelle
Richten Sie mehrere Konten ein und wählen Sie bei jeder Anforderung eines nach dem Zufallsprinzip aus oder ändern Sie das Konto, das Sie etwa jede Stunde verwenden. Auf diese Weise können Sie die Last auf
n
Konten verteilen und so bis zun
mal höhere Limits erhalten.Seien Sie vorsichtig, wenn Sie versuchen, andere Benutzer zu finden, die dies tun, wenn dies für Kunden nicht zulässig ist.
quelle