Rails - 基于用户凭据的每个请求的数据库连接

时间:2012-07-26 08:55:41

标签: ruby-on-rails session exchangewebservices

我们遇到以下问题:我们的应用程序通过其交换Web服务(EWS)与交换接口,您可以将其视为一个奇特的数据库。 例如,我们有一个约会模型,应该与Exchange上的日历同步。现在,EWS需要每个连接的用户凭据。这会产生两个问题:

  • 我们如何在每次请求时获取用户凭据?
  • 该模型应该如何与EWS互动?

我们不想做的是询问用户在需要与EWS交互的每个操作上的密码。我们也不想牺牲安全。

我们目前的解决方案:

我们在会话中存储来自用户(我们在登录期间获得)的凭据。 这很难看,因为这意味着用户名和密码存储在客户端计算机上的cookie中 - 我知道它是加密的,但它仍然很难看。

然后在控制器中,我们懒洋洋地创建一个EWS客户端并将其传递给需要与EWS交互的每个模型实例。 这很难看,因为这意味着与其他数据库操作不同(并且您可以将EWS视为另一个数据库),这意味着您必须为每个操作执行其他步骤。

示例(简化/剥离):

# app/models/appointments.rb
class Appointment
  attr_writer :ews

  def pull_from_exchange
    exchange_event = ews.events[exchange_id, exchange_change_key]
    # …update from exchange_event.to_hash…

    self
  end

  def push_to_exchange
    exchange_event = ews.events.new(to_hash_for_exchange)
    exchange_event.save
    update_attributes(exchange_id: exchange_event.id, exchange_change_key: exchange_event.change_key)

    self
  end

  def ews
    raise EwsClientNotProvided unless @ews
    @ews
  end

  def save_and_push!
    self.class.transaction do
      save!
      push_to_exchange
    end
  end
end

# app/controllers/appointments_controller.rb
class AppointmentsController < ApplicationController
  def create
    @appointment = Appointment.new(params[:appointment])
    @appointment.ews = ews
    @appointment.save_and_push!
  end

private
  def ews
    @ews ||= Ews.client(session.slice(:username, :password, :email).merge(endpoint: ews_endpoint))
  end

  def ews_endpoint
    Rails.application.configuration.ews_endpoint
  end
end

我对替代和/或更好的设计感兴趣来处理这种情况。

有任何想法/建议吗?

1 个答案:

答案 0 :(得分:1)

对于数据库连接,我建议在rackapp中使用Thread.current[],伪全局变量有时是必要的恶意。

在客户端上存储用户凭据是最佳解决方案,您可以使用另一种加密技术来加密密码字段,以防止暴力破解。这是因为cookie经过哈希处理,因此有可能对其进行强制执行,因为可以检查解密在本地成功的位置。如果将凭据存储在服务器上的某个位置,则在服务器被黑客攻击时会破坏所有密码。如果您在客户端存储数据,则它们更安全,因为您需要两个部分(服务器上的密钥和cookie)。