我们将在Sinatra中开发一个小型API应用程序。有哪些身份验证选项可用于保护API调用?
Sinatra 没有内置的身份验证支持。虽然有一些可用的 gem,但大多数都是为用户身份验证(即为网站)而设计的。对于 API 来说,它们似乎过于复杂。制作自己的身份验证非常容易。只需在每个路由中检查请求参数,以查看它们是否包含有效的 API 密钥,如果没有,则返回 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
如果您的`valid_key?`方法返回false,则调用`error`后不会发生任何事情 - `error`内部调用`halt`,这将停止请求继续。
当然,在每个路由的开头重复检查并不理想。相反,您可以创建一个小扩展程序,向您的路由添加条件:
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
如果你希望在所有路由上进行身份验证,可以使用一个 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/提供了一个稍微详细一些的答案,使用用户令牌。
这比API密钥更加复杂,但如果您的API需要身份验证以登录用户来执行诸如编辑名称/电子邮件/密码或访问每个用户信息(即“私有”API操作)等操作,则是必需的。 您还可以撤销/过期用户令牌,以便让人们注销等。
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