59 Stimmen

Sinatra - API - Authentifizierung

Wir werden eine kleine API-Anwendung in Sinatra entwickeln. Welche Authentifizierungsoptionen stehen zur Verfügung, um die API-Aufrufe zu sichern?

92voto

Todd Yandell Punkte 14578

Sinatra hat keine eingebaute Authentifizierungsunterstützung. Es gibt zwar einige Edelsteine, aber die meisten sind für die Benutzerauthentifizierung (d.h. für eine Website) gedacht. Für eine API scheinen sie ein Overkill zu sein. Es ist einfach genug, seine eigene zu machen. Überprüfen Sie einfach die Request-Params in jeder Ihrer Routen, um zu sehen, ob sie einen gültigen API-Schlüssel enthalten, und wenn nicht, geben Sie einen 401-Fehler zurück.

helpers do
  def valid_key? (key)
    false
  end
end

get "/" do
  error 401 unless valid_key?(params[:key])

  "Hello, world."
end

#  $ irb -r open-uri
#  >> open("http://yourapp.com/api/?key=123")
#  OpenURI::HTTPError: 401 Unauthorized

Nichts nach dem Aufruf von error wird passieren, wenn Ihr valid_key? Methode gibt false zurück -  error ruft auf. halt intern, was die Fortsetzung der Anfrage verhindert.

Natürlich ist es nicht ideal, die Prüfung zu Beginn jeder Strecke zu wiederholen. Stattdessen können Sie eine kleine Erweiterung erstellen, die Bedingungen zu Ihren Routen hinzufügt:

class App < Sinatra::Base
  register do
    def check (name)
      condition do
        error 401 unless send(name) == true
      end
    end
  end

  helpers do
    def valid_key?
      params[:key].to_i % 2 > 0
    end
  end

  get "/", :check => :valid_key? do
    [1, 2, 3].to_json
  end
end

Wenn Sie nur eine Authentifizierung für alle Ihre Routen wünschen, verwenden Sie eine before Handler:

before do
  error 401 unless params[:key] =~ /^xyz/
end

get "/" do
  {"e" => mc**2}.to_json
end

7 Stimmen

Todd Yandell, vielen Dank für die ausführliche Antwort und für die Zeit, die Sie dafür aufgewendet haben. Ich weiß das wirklich zu schätzen. Das ist wirklich hilfreich. Imran

0 Stimmen

Eine kleine Erweiterung zu erstellen scheint übertrieben, ein vorheriger Filter reicht aus, da letzterer die Option hat, welche Routen anzuwenden sind. Sie können das auch im Körper des Filters anhand von request.path_info erkennen.

2voto

chug2k Punkte 4818

http://www.secondforge.com/blog/2014/11/05/simple-api-authentication-in-sinatra/ hat eine etwas ausführlichere Antwort, die Benutzer-Tokens verwendet.

Dies ist ein Schritt komplizierter als ein API-Schlüssel, aber notwendig, wenn Ihre API eine Authentifizierung benötigt, um einen Benutzer anzumelden, um Dinge wie die Bearbeitung eines Namens/E-Mail/Passworts oder den Zugriff auf benutzerspezifische Informationen durchzuführen. (d. h. "private" API-Aktionen). Sie können Benutzer-Token auch widerrufen/ablaufen lassen, um Personen abzumelden usw.

class App < Sinatra::Base

  before do
    begin
      if request.body.read(1)
        request.body.rewind
        @request_payload = JSON.parse request.body.read, { symbolize_names: true }
      end
    rescue JSON::ParserError => e
      request.body.rewind
      puts "The body #{request.body.read} was not JSON"
    end
  end

  post '/login' do
    params = @request_payload[:user]

    user = User.find(email: params[:email])
    if user.password == params[:password] #compare the hash to the string; magic
      #log the user in
    else
      #tell the user they aren't logged in
    end
  end
end

(Es ist erwähnenswert, dass es üblicher ist, Anmeldeinformationen aus einem HTTP-Header statt aus dem JSON-Body zu lesen, aber das erwähnt der Autor nicht).

2voto

Marcelo Fonseca Punkte 1473

Update

Heutzutage wird die Token-basierte Authentifizierung immer beliebter. Ich würde empfehlen, die Ruby-Implementierung des JWT-Standards von ruby-jwt zur einfachen Authentifizierung und Autorisierung.

gem 'jwt'

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X