2010-08-13 24 views
56

Vamos a desarrollar una pequeña aplicación de API en Sinatra. ¿Cuáles son las opciones de autenticación disponibles para asegurar las llamadas API?Sinatra - API - Autenticación

Respuesta

88

Sinatra no tiene soporte de autenticación incorporado. Hay algunas gemas disponibles, pero la mayoría están diseñadas para la autenticación de usuarios (es decir, para un sitio web). Para una API, parecen exagerados. Es bastante fácil hacer la tuya. Simplemente verifique los parámetros de solicitud en cada una de sus rutas para ver si contienen una clave API válida, y si no, devuelva un error 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 

Nada después de la llamada a error sucederá si su método de valid_key? devuelve false - error llama halt internamente, que para la solicitud de continuar.

Por supuesto, no es ideal repetir el control al comienzo de cada ruta. En su lugar, puede crear una pequeña extensión que añade condiciones a sus rutas:

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 lo que desea es la autenticación en todas sus rutas, utilice un controlador de before:

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

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

Todd Yandell, muchas gracias por la respuesta detallada y por el tiempo que pasó en ella. Realmente lo aprecio. Es realmente ayuda. Imran – Saim

+0

La creación de una extensión pequeña parece excesiva, un filtro anterior es suficiente, ya que este último tiene la opción de decidir qué rutas aplicar. También puede indicarlo desde el cuerpo del filtro mediante request.path_info. – Robert

2

http://www.secondforge.com/blog/2014/11/05/simple-api-authentication-in-sinatra/ tiene un poco más detallada respuesta que usa tokens de usuario.

Esto es un paso más complicado que una clave API, pero es necesario si su API necesita autenticación para iniciar sesión en un usuario para hacer cosas como editar un nombre/correo electrónico/contraseña o acceder a información por usuario. (es decir, acciones API "privadas"). También puede revocar/expirará tokens de usuario para que la gente se desconectan, 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 

(Vale la pena señalar que es más común leer las credenciales de una cabecera HTTP en lugar del cuerpo JSON, pero el autor menciona que .)