2008-10-29 4 views
65

Ich beginne mit dem Aufbau einer REST-API für ein Projekt, an dem ich arbeite, und es führte mich zu ein wenig Forschung über den besten Weg Erstellen Sie eine API mit RoR. Ich finde ziemlich schnell heraus, dass Modelle standardmäßig für die Welt offen sind und über URL aufgerufen werden können, indem einfach eine ".xml" am Ende der URL platziert und entsprechende Parameter übergeben werden.Ich suche nach Vorschlägen für den Aufbau einer sicheren REST-API in Ruby on Rails

Also dann kam die nächste Frage. Wie sichere ich meine App, um nicht autorisierte Änderungen zu verhindern? Bei einigen Nachforschungen fand ich ein paar Artikel über attr_accessible und attr_protected und wie sie verwendet werden können. Die spezielle URL, über die ich sprach, wurde im Mai 2007 geposted (here).

Wie bei allen Dingen Rubin bin ich mir sicher, dass sich die Dinge seitdem entwickelt haben. Also meine Frage ist, ist dies immer noch der beste Weg, um eine REST-API in RoR zu sichern?

Wenn nicht, was schlagen Sie in einem Szenario "neues Projekt" oder "bestehendes Projekt" vor?

+0

Wenn der Client weiß, wie er Ihre URIs manipuliert (durch Anhängen von .xml oder anderen), dann ist Ihre API nicht REST. – aehlke

+0

das ist eine gute Oauth 2.0 Server-Bibliothek für Ruby https://github.com/Lelylan/rest-oauth2-server – sparkle

Antwort

100

Es gibt verschiedene Schemata zum Authentifizieren von API-Anfragen. Diese unterscheiden sich von der normalen Authentifizierung, die von Plugins wie restful_authentication oder acts_as_authenticated bereitgestellt wird. Am wichtigsten ist, dass Clients keine Sitzungen verwalten, daher gibt es kein Konzept für eine Anmeldung.

HTTP-Authentifizierung

können Sie grundlegende HTTP-Authentifizierung verwenden. Dazu werden API-Clients einen regulären Benutzername und Passwort verwenden und es nur in der URL setzen wie so:

http://myusername:[email protected]/ 

glaube ich, dass restful_authentication dies aus der Box unterstützt, so dass Sie, ob jemand ignorieren können, ist mit Ihre App über die API oder über einen Browser.

Ein Nachteil hier ist, dass Sie Benutzer sind gefragt ihre Benutzername und das Passwort im Klartext in jeder Anfrage zu stellen. Indem Sie dies über SSL tun, können Sie dies sicher machen.

Ich glaube nicht, dass ich jemals tatsächlich eine API gesehen habe, die dies verwendet. Es scheint mir eine anständige Idee zu sein, zumal es von den aktuellen Authentifizierungsschemata sofort unterstützt wird, daher weiß ich nicht, was das Problem ist.

API Key

Eine weitere einfache Möglichkeit API-Authentifizierung zu aktivieren ist API-Schlüssel zu verwenden. Es ist im Wesentlichen ein Benutzername für einen Remote-Dienst. Wenn sich jemand für die Verwendung Ihrer API anmeldet, geben Sie ihm einen API-Schlüssel. Dies muss bei jeder Anfrage bestanden werden.

Ein Nachteil dabei ist, dass, wenn jemand API jemand anderen Schlüssel bekommt, können sie diesen Benutzer Anfragen in so. Ich denke, wenn Sie alle Ihre API-Anfragen HTTPS (SSL) verwenden, können Sie dieses Risiko etwas ausgleichen.

Ein weiterer Nachteil ist, dass die Benutzer die gleichen Authentifizierungsinformationen verwenden (die API-Schlüssel) überall sie gehen. Wenn sie den Zugriff auf einen API-Client widerrufen wollen, besteht die einzige Möglichkeit darin, ihren API-Schlüssel zu ändern, wodurch auch alle anderen Clients deaktiviert werden. Dies kann gemildert werden, indem Benutzern ermöglicht wird, mehrere API-Schlüssel zu generieren.

API Key + Secret Key Unterzeichnung

Veraltet (Art) - siehe OAuth unter

Deutlich komplexer ist die Anforderung mit einem geheimen Schlüssel signieren. Dies ist, was Amazon Web Services (S3, EC2 und so) tun. Im Wesentlichen geben Sie dem Benutzer zwei Schlüssel: seinen API-Schlüssel (dh seinen Benutzernamen) und seinen geheimen Schlüssel (dh sein Passwort). Der API-Schlüssel wird mit jeder Anfrage übertragen, der geheime Schlüssel jedoch nicht. Stattdessen wird es zum Signieren jeder Anfrage verwendet, normalerweise durch Hinzufügen eines anderen Parameters.

IIRC, erreicht Amazon dies auf die Anforderung alle Parameter nehmen und sie durch Parameternamen zu bestellen. Dann wird diese Zeichenfolge gehashed, wobei der geheime Schlüssel des Benutzers als Hash-Schlüssel verwendet wird. Dieser neue Wert wird als neuer Parameter an die Anfrage angehängt, bevor sie gesendet wird. Auf der Seite von Amazon tun sie das Gleiche. Sie nehmen alle Parameter (außer der Signatur), ordnen sie an und haseln mit dem geheimen Schlüssel. Wenn dies mit der Signatur übereinstimmt, wissen sie, dass die Anfrage legitim ist.

Der Nachteil ist hier Komplexität. Die korrekte Funktionsweise dieses Schemas ist sowohl für den API-Entwickler als auch für die Clients ein Problem. Erwarten Sie viele Support-Anrufe und wütende E-Mails von Client-Entwicklern, die Dinge nicht zum Laufen bringen können.

OAuth

, um einige der Komplexität Probleme mit Schlüssel + geheimen Unterschrifts zu bekämpfen, hat sich zu einem Standard OAuth genannt entwickelt. Im Kern ist OAuth eine Variante von Key + Secret Signing, aber vieles davon ist standardisiert und wurde in libraries for many languages aufgenommen.

Im Allgemeinen ist es sowohl für den API-Produzenten als auch für den Konsumenten viel einfacher, OAuth zu verwenden, als ein eigenes Schlüssel/Signatur-System zu erstellen.

OAuth segmentiert auch inhärent den Zugriff und stellt unterschiedliche Zugangsdaten für jeden API-Benutzer bereit. Dadurch können Benutzer den Zugriff selektiv widerrufen, ohne ihre anderen konsumierenden Anwendungen zu beeinträchtigen.

Speziell für Ruby gibt es eine OAuth gem, die Unterstützung für OAuth-Produzenten und -Käufer bietet. Ich habe dieses Juwel verwendet, um eine API zu erstellen und auch OAuth APIs zu konsumieren und war sehr beeindruckt. Wenn Sie der Meinung sind, dass Ihre Anwendung OAuth benötigt (im Gegensatz zum einfacheren API-Schlüsselschema), kann ich Ihnen die Verwendung des OAuth-Edelsteins empfehlen.

+0

viele Leute gehen den API-Schlüssel + Signierpfad hinunter, jeder weiß, ob es einen "besseren Weg" gibt? ! – MatthewFord

+0

Schöne Antwort - das hat es für mich endlich mit den verschiedenen Levels geklärt. Vielen Dank! –

+2

Es gibt zwei große Probleme mit HTTP "Authorization:". Der erste ist, dass der Server über das Authentifizierungsschema entscheidet, was bedeutet, dass die Digest-Authentifizierung die Passwort-Kompromittierung durch ein MITM nicht verhindert (nur so tun, als ob Sie nur Basic unterstützen). Die zweite besteht darin, dass die Standardauthentifizierung nicht auf einen Pfad beschränkt ist, so dass jeder auf einem freigegebenen Webserver das Passwort eines anderen Benutzers erhalten kann (viele Leute wechseln aus diesem Grund zu Subdomains, zusammen mit Cookies und generell einer vernünftigeren Apache-Konfiguration). –

3

Ich stehe vor ähnlichen Fragen wie Sie im Moment, weil ich auch eine REST API für eine Rails-Anwendung aufbaue.

Ich schlage vor sicherzustellen, dass nur Attribute, die Benutzer bearbeitet werden können, mit attr_accessible markiert sind. Dadurch wird eine weiße Liste von Attributen erstellt, die mit update_attributes zugewiesen werden können.

Was ich tue, ist so etwas wie dieses:

class Model < ActiveRecord::Base 
     attr_accessible nil 
    end 

Alle meine Modelle aus, dass erben, so dass sie gezwungen sind, attr_accessible für alle Felder zu definieren, sie Masse zuordenbar machen wollen. Persönlich wünschte ich, dass es eine Möglichkeit gäbe, dieses Verhalten standardmäßig zu aktivieren (es könnte sein, und ich weiß es nicht).

Nur damit Sie wissen, dass jemand eine Eigenschaft nicht nur mit der REST-API zuweisen kann, sondern auch mit einem regulären Formular-Post.

7

Wie sichere ich meine App, um nicht autorisierte Änderungen zu verhindern?

attr_accessible und attr_protected sind sowohl nützlich zur Steuerung der Fähigkeit Massenzuordnungen auf einem Active Modell auszuführen. Sie möchten auf jeden Fall attr_protected verwenden, um Forminjektionsangriffe zu verhindern. siehe Use attr_protected or we will hack you.

Um zu verhindern, dass jemand auf die Controller in Ihrer Rails-App zugreifen kann, werden Sie fast sicher eine Art von Benutzerauthentifizierungssystem benötigen und eine before_filter in Ihre Controller stellen, um sicherzustellen, dass Sie über eine berechtigter Benutzer, der die Anfrage durchführt, bevor Sie die Ausführung der angeforderten Controller-Aktion zulassen.

Sehen Sie die Ruby on Rails Security Guide (Teil des Rails Documentation Project) für Tonnen mehr hilfreiche Informationen.

0

Ein anderer Ansatz, der das Erstellen einer Menge der Sachen selbst speichert, ist etwas wie http://www.3scale.net/ zu verwenden, das Schlüssel, Token, Quoten usw. für einzelne Entwickler behandelt. Es macht auch Analysen und erstellt ein Entwicklerportal.

Es gibt ein ruby ​​/ rails-Plugin ruby API plugin, das für Richtlinien gilt, die für den Datenverkehr gelten, wenn es ankommt - Sie können es in Verbindung mit der oAuth gem verwenden. Sie können es uns auch, indem Sie Lack vor der App ablegen und den Lack lib mod: Varnish API Module verwenden.