在Ruby中使用REST API - 何时进行身份验证?

时间:2016-10-02 07:33:27

标签: ruby rest

我会尽量保持这一点,尽可能简短。

我正在编写一个以gemmat gem为模型的Ruby gem,它是产品REST API的包装器。我正在使用的API使用基于令牌的身份验证;通过POST发送API令牌,并以cookie的形式返回会话。我正在使用Faraday cookiejar中间件来处理API返回的cookie。从概念上讲,我正在努力解决的问题是何时进行身份验证。

我有两个类,一个叫做RestClient,另一个叫做Volume;后者继承自前者。现在,RestClient的init方法构建一个连接对象并进行身份验证,而Volume的init方法调用super并传递路径。我的想法是,当任何继承自RestClient的类被初始化时,它将验证用户。

class RestClient
  def initialize(api_path)
    <build connection>
    auth
  end
  def auth
    <post token, get session cookie>
  end
end

class Volume < RestClient
  def initialize
    super('/volume')
  end
  def volumes
    <send GET, receive volumes>
  end
end

obj = Volume.new #Creates object, authenticates user
obj.volumes #Returns list of volumes

我想我的问题是..我走向正确的轨道?我应该暂停身份验证,直到首先在对象上调用方法,而不是在初始化时进行身份验证?我完全错误地解决了这个问题吗?

2 个答案:

答案 0 :(得分:0)

你在这里问的更多是一个代码风格的问题。这里没有对错。我即将投票结束,因为我认为它是primarily opinion-based

因为我有意见,所以我会写一个答案。

a)不要过度思考

只是实现这些东西,如果有效,那就足够了

b)3的规则

如果你已经实现了3种相同类型的东西并且出现了一种模式,那么重构!

c)拒绝使用继承

如有疑问,请勿使用继承。一个模块在大多数时候都会很好。

具体问题:

我不会使用初始化程序来进行http调用。它们容易出错,并且在初始化程序或其周围的错误处理真的很难看。它使测试中的痛苦。

我要做的就是用简单的方法实现你需要的任何东西。

在拨打另一个api电话之前调用authenticate有什么问题?将它放入一个块可能会使它非常好看和可读:

client.authenticate do |session|
  session.volumes
end

如果这对你的用例来说太难看了,你可以在任何其他可能需要身份验证的方法调用之前懒散地进行。

答案 1 :(得分:0)

Cookie是您支持的唯一身份验证吗?通常,面向服务器(服务器到服务器)的REST API还可以实现更好的身份验证策略,允许您在每次请求时传递身份验证。

所有这一切,你还可以做的是这样的事情:

 client = MyApi::Client.for_user(username: ..., password: ....)
 #...or
 client = MyApi::Client.for_token(token)
 volumes = MyApi::Volumes.get(client: client)

这种方式对于需要auth的地方,你会通过“鼓励你的类正确使用”来做一件好事 - 你根本不会在没有认证数据的情况下实例化客户端,并且不会初始化你的远程没有客户的对象/电话。

然后,在客户端内,您可以做的是第一次请求时的memoized auth

def perform(http_method, url, ...)
  @auth_cookie ||= @client.get_cookie_by_authentication
  ...
end