2010-08-13 6 views
56

Nous allons développer une petite application API dans Sinatra. Quelles sont les options d'authentification disponibles pour sécuriser les appels d'API?Sinatra - API - Authentification

Répondre

88

Sinatra ne dispose pas d'un support d'authentification intégré. Il y a quelques gemmes disponibles, mais la plupart sont conçues pour l'authentification d'utilisateur (c.-à-d. Pour un site Web). Pour une API, ils semblent exagérés. C'est assez facile de faire les vôtres. Vérifiez simplement les paramètres de requête dans chacune de vos routes pour voir s'ils contiennent une clé API valide et, dans le cas contraire, renvoyez une erreur 401.

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 

Rien après l'appel à error se produira si votre valid_key? méthode retourne false - error appelle en interne halt, qui arrête la demande de continuer.

Bien sûr, il n'est pas idéal de répéter la vérification au début de chaque route. Au lieu de cela, vous pouvez créer une petite extension qui ajoute des conditions à vos routes:

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 

Si vous voulez juste l'authentification sur tous vos itinéraires, utilisez un gestionnaire before:

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

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

Todd Yandell, merci beaucoup pour la réponse détaillée et pour le temps que vous y avez consacré. J'apprécie beaucoup. Cela aide vraiment. Imran – Saim

+0

La création d'une petite extension semble excessive, un filtre avant suffit, puisque cette dernière a la possibilité de choisir les routes à appliquer. Vous pouvez également le dire à partir du corps du filtre par request.path_info. – Robert

2

http://www.secondforge.com/blog/2014/11/05/simple-api-authentication-in-sinatra/ a un peu plus détaillée réponse qui utilise des jetons utilisateur. Ceci est une étape plus compliquée qu'une clé API, mais elle est nécessaire si votre API a besoin d'une authentification pour se connecter à un utilisateur pour modifier un nom/email/mot de passe ou accéder à des informations par utilisateur. (c'est-à-dire des actions d'API "privées"). Vous pouvez également révoquer/expireront jetons d'utilisateur de laisser les gens se déconnectent, etc.

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 

(Il vaut la peine de noter qu'il est plus fréquent de lire des informations d'identification d'un en-tête HTTP au lieu du corps JSON, mais l'auteur mentionne que .)