rails在会话中存储密码

时间:2011-11-17 09:26:17

标签: ruby-on-rails session

我有一个使用web api调用的rails应用程序,rails app本身没有任何数据库或用户界面。每个api调用都需要为每个请求发送用户名和密码。

我想为rails app提供身份验证机制。 我打算这样做:

  1. 显示登录页面
  2. 获取用户名和密码
  3. 存储用户名和密码
  4. 通过warden.authenticate或authlogic.something执行手动身份验证(或者甚至可能不需要检查会话是否存储了某些内容)
  5. 然后当用户做某事时,我会传递先前存储的用户名和密码。
  6. 现在我的问题是我在哪里存储密码? 如果我使用会话我显然不能使用cookie存储,我可以使用session_store = :active_record_store但不确定它是否安全,我现在还没有任何数据库所以为什么我要创建一个仅用于会话? 是否有其他机制可以在会话中存储密码? (显然是安全的方式)

    早期的铁路有:

    • MemoryStore的
    • FileStore的

    但现在两者似乎都被删除了。那么任何其他解决方案?

    答案中的注释:

    1. 存储加密密码不起作用,因为我需要在进行api调用时将原始密码发送到服务器。
    2. 我无法控制API,因此无法更改其身份验证。
    3. rails应用程序上没有用户配置文件维护。由API调用管理的所有内容。
    4. 我终于想到实现自定义内存存储但似乎抛出stackoverflow错误。我从https://rails.lighthouseapp.com/projects/8994/tickets/1876-uninitialized-constant-actioncontrollersessionmemorystore

      获得了代码
      require 'action_dispatch'
      module ActionDispatch
      module Session
      class CustomMemoryStore < ActionDispatch::Session::AbstractStore
        GLOBAL_HASH_TABLE = {} #:nodoc:
      
        private
          def get_session(env, sid)
            sid ||= generate_sid
            session = GLOBAL_HASH_TABLE[sid] || {}
            session = AbstractStore::SessionHash.new(self, env).merge(session)
            [sid, session]
          end
      
          def set_session(env, sid, session_data)
            GLOBAL_HASH_TABLE[sid] = session_data
            return true
          end
        end
       end
      end
      Steptools3::Application.config.session_store :custom_memory_store, :key => '_some_xyz'
      

4 个答案:

答案 0 :(得分:2)

您可以尝试将Redis用作会话商店。我们使用rails3-redis-session-store gem。可以找到来源here

设置非常简单,会话会自动过期,这样可以确保安全。 示例配置:

YourApp::Application.config.session_store :redis_session_store,
                                          :db => 0,
                                          :expire_after => 10.minutes,
                                          :key_prefix => "your_app:session:"

另一种方法是使用dalli,然后使用memcached作为后端。

希望这有帮助。

答案 1 :(得分:1)

我建议采取下一步并设置一个简单的数据库,为自己和用户节省很多麻烦,当用户想要返回网站时会发生什么,他们将不得不重新注册。

我发现Devise非常适合此目的,并且非常易于集成。

如果您不希望运行经典数据库服务器,可能需要查看MongoDB

答案 2 :(得分:1)

会话cookie使用会话密钥加密。只要您保持会话密钥的强大(128字符)并且安全,您的数据就应该是安全的。

ActionController::Base.session = {
  :key         => '_foo_bar_session',
  :http_only   => true,
  :secret      => 'dldkdke420934indsknknkfsnh318u84e9u49832dfkdsajdsk'
}

如果要将身份验证详细信息存储在浏览器会话之外,则可以将其存储在已签名的永久性Cookie中。

cookies.permanent.signed[:user_credentials] = [login, password]

签名的cookie可以像普通的cookie一样访问:

cookies[:user_credentials]

确保在初始化文件中设置了强大的cookie_verifier_secret

ActionController::Base.cookie_verifier_secret ='dskjkjfdshfddsfkhkr3898398430943'

<强>参考

Signed and Permanent cookies in Rails 3

答案 3 :(得分:1)

我会尝试分析您的选择:

如果服务器被CustomMemoryStore

攻击

考虑以下情况:

  • 4用户A,B,C,D已登录。
  • 您的服务器被黑了。黑客获得服务器的控制权。
  • D做了一些操作。
  • 您发现您的服务器遭到黑客入侵,并修复了您的系统。

使用CustomMemoryStore,黑客可以获取所有用户的密码。在运行Rails进程中注入一些逻辑或者转储内存和分析并不困难。在ActiveRecord,MongoDB,Redis中存储密码也有类似的问题。

如果服务器被CookieStore攻击?

如果出现上一个场景并且您正在使用CookieStore会怎样?

让我们回顾一下CookieStore的机制:

  • 服务器有一个密钥签名&amp;验证会话。
  • 每次浏览器发送请求时,服务器都会解密会话,修改数据,签署会话,并将会话发送到cookie中的浏览器。

换句话说,黑客无法从cookie或密钥中获取密码。他需要cookie和密钥来窃取密码。

在这种情况下,A,B,C的密码是安全的。只有D的密码才会被黑客窃取。您可以尽快修复系统,以尽量减少损坏。

CustomMemoryStore的问题

除了安全问题,我知道您知道CustomMemoryStore不可扩展。但是,问题可能比您想象的要大。您将在控制器操作中向其他Web服务发送请求,如果远程服务缓慢或关闭,它将阻止整个服务器。即使您只有1到10个并发用户,也可能会很痛苦。

即使您决定在单个服务器上运行应用程序,也可以使用Passenger或Unicorn启动多个rails进程。 CustomMemoryStore拒绝这些选项。

客户安全问题

如果担心从浏览器端窃取cookie,您可以考虑EncryptedCookieStore。它加密会话并存储在客户端cookie中。如果您只有cookie或密钥,则无法获取密码。您需要cookie和密钥来解密密码。

关键问题是什么?

EncryptedCookieStore更安全,因为它将加密密码存储在用户的cookie中,并且密钥仅在服务器上可用。如果黑客只有cookie或密钥,他就无法获得密码 - 他需要密码。

当然,您可以使用CustomMemoryStore实现类似的逻辑。例如,将加密密码存储在服务器内存中,并且单个密钥位于cookie中。如果您仍决定在服务器上存储加密密码,我建议您使用Redis进行存储。与MySQL和MongoDB相比,它简单快捷。由于扩展问题,不建议使用CustomMemoryStore。

其他建议

其他系统的密码是非常敏感的数据,你应该非常小心处理安全问题。如果是公共服务,您应该非常仔细地写下您的服务条款和免责声明协议。此外,您应该使用HTTPS运行您的服务。

<强> TL; DR

  • 如果可以,请使用OAuth(嗯,我知道你不能)
  • EncryptedCookieStore应该简单而安全。
  • 如果您决定在服务器上存储密码,请对其进行加密并将密钥存储在客户端(cookie)。