4

我正在使用 Sinatra 构建一个 API,它应该能够管理向其发送请求的任何客户端应用程序的用户登录会话。到目前为止(对于登录功能),我得到的是 /login 的路由,如果用户凭据有效,则会在 RDBMS 中创建一个 AccessToken。见下文:

    #
    # Login
    #
    post '/login' do
      if (@input["email"].nil? || @input["password"].nil?) then
        response = {
          "success" => false,
          "msg" => "Email and password must be provided"
        }
        $log.error "Email or password not sent to /login"
        return response.to_json
      end

      email     = @input["email"]
      password  = Digest::SHA2.hexdigest(@input["password"])

      user = User.where(:email => email, :password => password).first
      if user.nil?
        response = {
          "success" => false,
          "msg" => "No users exist with that email/password combo"
        }
        $log.error "Invalid Email or Password sent to /login"
        return response.to_json
      end

      token = AccessToken.new(:user_id => user.id)
      token.save!

      $log.info "User valid. Logged in. Token: #{token.token}"
      response = {
        "success" => true,
        "msg" => "User logged in",
        "data" => {"token" => token.token}
      }
      return response.to_json
    end

然后对于需要身份验证的任何其他路由,我正在检查令牌是否作为请求的参数发送,例如:

    #
    # Return Clients for User
    #
    # get '/clients/:token' do
    get '/clients' do
      token = AccessToken.where(:token => params[:token]).first
      @current_user = User.find(token.user_id) unless token.nil?

      if @current_user.nil?
        response = {
          "success" => false,
          "msg" => "User must be logged in to do this"
        }
        $log.error "User is not logged in"
        return response.to_json
      end

      response = {
        "success" => true,
        "msg" => "Clients successfully retrieved",
        "data" => {"clients" => @current_user.clients}
      }
      $log.info "Clients successfully retrieved"
      return response.to_json
    end

所以我想知道:(a)这是一种使用 API 处理用户会话的好/稳健的方法,以及(b)是否有在客户端(iOS、Android 和 Web 应用程序)处理它的标准方法?他们是否应该将访问令牌存储在会话变量中,然后在每个请求中将令牌添加到正在发送的参数中?

谢谢!

4

1 回答 1

1

查看 JSON Web Tokens 以了解交换令牌的标准化方式:http: //jwt.io/

对于 Sinatra 部分,您可以使用以下模式来避免重复授权代码:

before do
  token = AccessToken.where(:token => params[:token]).first
  @current_user = User.find(token.user_id) unless token.nil?
end

注册一个认证方法:

register do
  def auth (type)
    condition do
      return {
        "success" => false,
        "msg" => "User must be logged in to do this"
      }.to_json unless @current_user
    end
  end
end

现在您可以将此要求添加到任何路线:

get '/clients', :auth => :user do
  # Your implementation
end
于 2015-08-12T13:47:41.803 回答