如何在Ruby(Rails/Sinatra)中实现客户端 - 服务器API和授权?

lif*_*der 5 ruby authentication api sinatra

我需要一个关于如何在ruby中实现"客户端 - 服务器"Web应用程序的建议.任何指南和最佳实践都非常感谢.我对Ruby方式和所需的宝石感兴趣,因为它是一个理想的平台,以及实现这些东西的一般方式和逻辑.

我不是一个优秀的红宝石程序员或熟练的系统设计师,可悲地多年,所以我真的需要你的帮助,因为我仍然希望这件事最终会闪耀.

应用程序的当前外观应如下所示:

DB + Auth DB < - > API App < - >其他应用:

  • 数据库 - 一个数据库或一组数据库,其中一个数据库用于用户组(区域).
  • Auth DB - 一个带有个人用户数据和登录信息的DB,即使主数据库在区域之间分割,也可能是单一的.
  • API应用程序 - 这个东西维护着围绕数据,访问控制和翻译的所有逻辑,可能为所有应用程序提供一个翻译基础.
  • 其他应用程序 - 一堆不同的应用程序,与API绑定,这可能是数据提供程序,它使用某些用户的一些数据和不同类型的UI来搜索API.所有应用程序都没有自己的用户相关信息存储空间,只能通过API处理数据.

API应用程序:看起来最好的工具是Sinatra.问题是:

  1. 如何以清晰的方式组织API?Rails为模型和控制器提供了很好的REST路径设置和文件夹结构.有什么提示或宝石可以提高API构建的实际效果吗?
  2. 如何保持访问?Warden看起来不是一个好选择,因为API客户端本身就是Web应用程序.所以我需要某种身份验证令牌.怎么可能呢?某种自定义OAuth提供商?问题是,我不喜欢通过API存储和传递会话cookie的想法,每个请求传递一些访问令牌.这也是

其他应用程序:主要是基于Web的UI.这部分的逻辑选择是Rails.主要问题是如何实现客户端身份验证.设计很酷,但它是否可以使用令牌,或者它是更合适的工具?

Flo*_*ian 5

好的,这会更长一些:

如果您已经熟悉Rails,可以查看Rails API gem.该项目努力从Rails中删除额外的基础,这是基于JSON的RESTful API不需要的.

这可能听起来很顺利,但它有它的缺点.首先,您可以阅读基本的导轨功能所需的所有内容,例如,您可能习惯使用的内容respond_to.这可能有点棘手,但是当您发现哪些rails模块最初提供了通常捆绑在Rails中的功能时,这非常简单ActionController::Base.

话虽这么说,让我举一个例子,说明我为好奇的上周做的小型API项目做了些什么:

初步情况

我们有一个主要完成的Rails应用程序.一切正常,但它基本上是单片的.一切都由Rails框架提供.对我们来说幸运的是,所有模型逻辑都捆绑在一个叫做的宝石中core.应用程序本质上允许登录的客户创建可通过最终用户视图搜索的产品.

目标是为此提供RESTful API,它可以更有效地处理并发和更大的数据文件(即CSV,XLS).

介绍Rails API

设计目标让我进入Rails API gem.基本安装在Rails中工作,除了调用脚本rails-api,即:

rails-api new jsonapi
Run Code Online (Sandbox Code Playgroud)

这里的优势在于我可以使用core其他应用程序,但没有什么能阻止我将自己的模型引入jsonapi应用程序.

话虽这么说,你可以做所有标准的Rails好东西,比如路由等.它遵循相同的约定.然后,标准路线最初只对JSON做出反应,有时可能会有点混乱.

让我举一个处理产品的API控制器的例子:

class ProductsController < ApplicationController
  include ActionController::HttpAuthentication::Token
  before_filter :find_product, :except => [:create, :index]

  def index
    render :json => @products
  end

  def create
    @product = product.new params[:product]

    if @product.save
      render :json => @product, :status => :created
    else
      render :json => @product.errors, :status => :unprocessable_entity
    end
  end

  def show
    render :json => @product
  end

  def update
    if @product.update_attributes params[:product]
      render :json => @product, :status => :ok
    else
      render :json => @product.errors
    end
  end

  def destroy
    if @product.destroy
      render :json => @product, :status => :ok
    else
      render :json => {:note => I18n.t("messages.deletion_impossible")}, :status => :unprocessable_entity
    end
  end

protected
  def find_product
    @product = Product.find params[:id]
  end
end
Run Code Online (Sandbox Code Playgroud)

没什么特别的.唯一需要注意的是ActionController::HttpAuthentication::Token显式包含的第二行.这样可以通过HTTP令牌保护您的aPI.如果您想了解有关保护API的更多信息,我建议Ryan Bates的Railscasts指南.

在本质上,您提供了一个之前的过滤器,ApplicationController如下所示:

class ApplicationController < ActionController::API  
  include ActionController::HttpAuthentication::Token::ControllerMethods
  [...]
  before_filter :restrict_access
  [...]
  def restrict_access
    authenticate_or_request_with_http_token do |token, options|
      # see if key is valid.
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

再次注意第二行,你必须ControllerMethods手动包含,否则没有控制器会知道authenticate_or_request_with_http_token.

延期

您可能知道基于Rails约定扩展API.它的工作方式完全相同,但默认情况下有些东西是故意丢失的.如果您在JSON模板中需要更多灵活性,我建议添加JBuilder(Railscast).

很好,但客户呢?

就个人而言,就客户而言,有很多选择.最终我发现它归结为你最喜欢的东西.我个人可以在Rails API之上推荐一个小的node.js层,然后在它前面获得一个基于backbone.js的单页面应用程序.如果您愿意,也可以尝试使用AngularJS.您还可以围绕它构建另一个Rails应用程序,并在控制器操作中调用API.

它还取决于您想要定位的平台 - 想到iOS/Android的本机应用程序.

我做的选择是node.js + backbone.它目前对我和项目最有意义.节点层基本上保存与API通信所必需的令牌,并且主干应用程序具有与节点层通信的小型库.但它可能是一把双刃剑,取决于你的API有多复杂.对于一个小例子,这看起来很好,但是可能有很多代码重复只是为了将来自主干应用程序的调用放到Rails API中.

认证

对于身份验证,您可以创建基于客户的API密钥(令牌),然后将控制器逻辑限制为仅接受该密钥允许的数据操作.您可以通过节点层管理会话.编辑:这是授权,而不是身份验证.实际上没有什么能阻止你使用Authlogic和Rails API - 我没有测试它,但它应该工作.

我承认我还没有完成这部分 - 我希望其他人可以回答这个架构问题:-)

我希望我能提供一些见解.

PS:如果你想测试你的API我强烈推荐httpie(真棒!)