2010-08-24 3 views
37

Ich bin beschäftigt portieren eine sehr kleine Web-App von ASP.NET MVC 2 nach Ruby/Sinatra.Was ist ein sehr einfaches Authentifizierungsschema für Sinatra/Rack

In der MVC-Anwendung wurde FormsAuthentication.SetAuthCookie verwendet, um ein dauerhaftes Cookie festzulegen, wenn die Benutzeranmeldung ordnungsgemäß für die Datenbank überprüft wurde.

Ich fragte mich, was wäre die Entsprechung von Forms Authentication in Sinatra? Alle Authentifizierungs-Frameworks erscheinen sehr sperrig und nicht wirklich das, wonach ich suche.

+3

Obwohl ich nicht einmal so tun werde, als ob dies eine Antwort auf Ihre Frage ist, werde ich darauf hinweisen, dass es von Natur aus gefährlich ist, ein eigenes Authentifizierungsschema zu entwerfen und zu entwickeln. Es gibt viele "Hacker", die anfangen zu sabbern, wenn sie solche Dinge finden. Es ist besser, etablierte, bewährte Tools dafür zu finden.Es ist kein neues Problem und es gibt bereits viele akzeptable Lösungen. – jaydel

+0

Verwenden Sie bcrypt gem. Es kann kryptische Hashes für Passwörter erzeugen und wenn ein Hacker auf Ihre Datenbank zugreift, bekommen sie nur die Hashes und sie sollten nicht für Passwörter funktionieren. Ich andere Worte, behalte es in einer Richtung. Sie werden sehr viel bcrypt-ruby sehen, aber jetzt ist es nur bcrypt und ist ein C-Erweiterungstyp, so dass Sie das mit Windows unter einigen hinzugefügten Entwicklungswerkzeugen kompilieren müssen. Du hast Recht, sie sind sperrig. https://sideprojectsoftware.com/blog/2015/02/22/sinatra-authentication sollte helfen. –

Antwort

73

Hier ist ein sehr einfaches Authentifizierungsschema für Sinatra.

Ich werde erklären, wie es unten funktioniert.

class App < Sinatra::Base 
    set :sessions => true 

    register do 
    def auth (type) 
     condition do 
     redirect "/login" unless send("is_#{type}?") 
     end 
    end 
    end 

    helpers do 
    def is_user? 
     @user != nil 
    end 
    end 

    before do 
    @user = User.get(session[:user_id]) 
    end 

    get "/" do 
    "Hello, anonymous." 
    end 

    get "/protected", :auth => :user do 
    "Hello, #{@user.name}." 
    end 

    post "/login" do 
    session[:user_id] = User.authenticate(params).id 
    end 

    get "/logout" do 
    session[:user_id] = nil 
    end 
end 

Für jede Route, die Sie schützen möchten, fügen Sie den :auth => :user Zustand, um es, wie im /protected Beispiel oben. Das ruft die Methode auth auf, die über condition eine Bedingung zur Route hinzufügt.

Die Bedingung ruft die Methode is_user? auf, die als Hilfsprogramm definiert wurde. Die Methode sollte True oder False zurückgeben, abhängig davon, ob die Sitzung eine gültige Konto-ID enthält. (Calling Helfer dynamisch wie dies macht es einfach, andere Arten von Benutzern mit unterschiedlichen Berechtigungen hinzuzufügen.)

Schließlich ist die before Handler richten ein @user Instanz-Variable für jede Anforderung für Dinge wie die Anzeige des Namen des Benutzers an der Spitze von jedem Seite. Sie können auch die is_user? Helfer in Ihren Ansichten verwenden, um festzustellen, ob der Benutzer angemeldet ist

+0

Erstens, danke für so eine gut durchdachte Antwort! Zweitens vergesse ich zu erwähnen, aber es wäre nett, wenn ich persistente Sitzungen haben könnte. Ich nehme an, dass, wenn ich etwas wie unten tun würde, dies die Sitzung dauerhaft machen würde? Rack :: Sitzung :: Cookie,: Geheimnis => "einige wirklich einzigartige Wert" Gibt es irgendwelche Sicherheitsprobleme mit diesem Ansatz, wenn das der Fall ist? – AndrewVos

+0

schön, eine Gelegenheit, mehr von Sinatra schönen DSL zu verwenden :) –

+0

aber wo sind die Benutzerdaten (Benutzername und Passwort) gespeichert? Wie können wir in erster Linie ein Benutzerkonto erstellen, damit er/sie sich authentifizieren kann !!! – Hanynowsky

27

Todds Antwort für mich nicht funktioniert, und ich fand eine noch einfachere Lösung für einmalige tot einfache Authentifizierung in Sinatra's FAQ.

require 'rubygems' 
require 'sinatra' 

use Rack::Auth::Basic, "Restricted Area" do |username, password| 
    [username, password] == ['admin', 'admin'] 
end 

get '/' do 
    "You're welcome" 
end 

Ich dachte, ich würde es teilen, nur für den Fall, dass jemand diese Frage wanderte und eine nicht persistente Lösung brauchte.

+0

Das ist erstaunlich, vielen Dank für das Teilen! –

+2

Todds Antwort funktioniert nicht wie sie ist, weil sie nicht vollständig ist, nicht weil sie falsch ist. Im Gegenteil, es ist eine ziemlich ausgeklügelte und gut durchdachte Lösung, es fehlt einfach ein "App.run!" Am Ende und natürlich die eigentliche Implementierung der 'User' Klasse (verantwortlich für das Berechtigungsmanagement). – p4010

1

ich die akzeptierte Antwort für eine App verwendet, die zwei Passwörter nur hatte, eine für Benutzer und eine für Administratoren. Ich habe gerade ein Login-Formular erstellt, das ein Passwort (oder eine PIN) annimmt und dieses mit einem Formular vergleicht, das ich in den Einstellungen von Sinatra eingerichtet habe (eines für den Administrator, eines für den Benutzer). Dann stelle ich die Sitzung [: current_user] entweder auf admin oder auf Benutzer, entsprechend dem Passwort, das der Benutzer eingegeben und entsprechend autorisiert hat. Ich brauchte nicht einmal ein Benutzermodell. Ich hatte so etwas wie dies zu tun:

use Rack::Session::Cookie, :key => 'rack.session', 
         :domain => 'foo.com', 
         :path => '/', 
         :expire_after => 2592000, # In seconds 
         :secret => 'change_me' 

Wie in den sinatra documentation erwähnt, die Sitzung beharren in Chrom zu erhalten. Wenn sie zu meiner Hauptdatei hinzugefügt werden, bleiben sie wie erwartet bestehen.