3

我们有以下问题:我们的应用程序通过其交换 Web 服务 (EWS) 与交换接口,您可以将其视为只是一个花哨的数据库。例如,我们有一个 Appointment 模型,它应该与 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

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

有什么想法/建议吗?

4

1 回答 1

1

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

将用户凭据存储在客户端是最佳解决方案,您可以使用另一种加密方式为密码字段添加趣味,以保护其免受暴力破解。这是因为 cookie 是经过哈希处理的,因此可以暴力破解它,因为可以在本地检查解密成功的位置。如果您将凭据存储在服务器上的某个位置,那么如果服务器被黑客入侵,所有密码都会被泄露。如果您将数据存储在客户端,它们会更安全,因为您需要这两个部分(服务器上的密钥和 cookie)。

于 2012-07-26T09:25:26.387 回答