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
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
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 .)
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
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