【问题标题】:Sinatra - API - AuthenticationSinatra - API - 身份验证
【发布时间】:2011-03-29 15:04:27
【问题描述】:

我们将在 Sinatra 中开发一个小的 API 应用程序。有哪些身份验证选项可用于保护 API 调用?

【问题讨论】:

    标签: api authentication sinatra


    【解决方案1】:

    Sinatra 没有内置的身份验证支持。有一些 gems 可用,但大多数都是为用户身份验证而设计的(即用于网站)。对于 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
    

    【讨论】:

    • Todd Yandell,非常感谢您提供详细的答案以及您花在这方面的时间。我真的很感激。这真的很有帮助。伊姆兰
    • 创建一个小扩展似乎有点过头了,一个前置过滤器就足够了,因为后者可以选择应用哪些路由。您还可以通过 request.path_info 从过滤器的主体中分辨出来。
    【解决方案2】:

    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
    

    (值得注意的是,从 HTTP 标头而不是 JSON 正文中读取凭据更为常见,但作者提到了这一点。)

    【讨论】:

      【解决方案3】:

      更新

      如今,基于令牌的身份验证越来越流行。 我建议使用 ruby-jwt 的 JWT 标准的 ruby​​ 实现来进行简单的身份验证和授权。

      gem 'jwt'
      

      【讨论】:

        猜你喜欢
        • 2012-04-12
        • 1970-01-01
        • 2013-08-21
        • 1970-01-01
        • 1970-01-01
        • 2016-04-12
        • 2016-04-24
        • 1970-01-01
        • 2011-11-28
        相关资源
        最近更新 更多