Rails ActiveSupport :: CachingKeyGenerator

时间:2019-05-21 08:13:14

标签: ruby-on-rails ruby encryption

要加密用户信息并将其存储在数据库中,我的Rails应用程序使用salt(每个用户)使用key生成ActiveSupport::KeyGenerator。但是,由generate_key方法执行的默认迭代为2**16 [1]。在每次读取(用于解密)和写入(用于加密)时,使用用户的salt执行密钥生成会使我的应用程序变慢。

我发现,如果用于密钥生成的ActiveSupport::CachingKeyGeneratorsalt保持不变,则length可用于缓存密钥[2]。在内部,它使用Concurrent::Map [3]来缓存密钥。使用ActiveSupport::CachingKeyGenerator可以提高应用程序的性能,因为它并不总是生成密钥。

这会将我的应用程序的内存使用率提高到可以使应用程序崩溃的程度吗?

参考文献:

  1. https://github.com/rails/rails/blob/b9ca94caea2ca6a6cc09abaffaad67b447134079/activesupport/lib/active_support/key_generator.rb#L16

  2. https://api.rubyonrails.org/classes/ActiveSupport/CachingKeyGenerator.html

  3. https://github.com/rails/rails/blob/b9ca94caea2ca6a6cc09abaffaad67b447134079/activesupport/lib/active_support/key_generator.rb#L33

1 个答案:

答案 0 :(得分:0)

共享“有效的”解决方案

由于ActiveSupport::CachingKeyGenerator使用Concurrent::Map,我发现高速缓存键将导致与用户数量成比例的内存使用量增加(假设所有请求都以某种方式路由到同一节点)。

为解决这个问题,我写了一个类似的CachingKeyGenerator,其中包含ActiveSupport::KeyGeneratorActiveSupport::Cache::MemoryStore

class CachingKeyGenerator
  BASE = Rails.application.secrets.secret_key_base
  LENGTH = ActiveSupport::MessageEncryptor.key_len
  KEY_EXPIRY = 1.day

  def initialize
    @key_generator = ActiveSupport::KeyGenerator.new(Rails.application.secrets.secret_key_base)
    @keys_cache = ActiveSupport::Cache::MemoryStore.new(expires_in: KEY_EXPIRY)
  end

  def generate_key(salt)
    key = @keys_cache.fetch(salt)
    if key.nil?
      key = @key_generator.generate_key(salt, LENGTH)
      @keys_cache.write(salt, key)
    end
    key
  end
end

根据Rails文档,ActiveSupport::Cache::MemoryStore是线程安全的,并实现了基于LRU的清除机制[1]。这应该使高速缓存的内存使用具有确定性-设置为内存存储的大小限制(默认值-32Mb,可以在初始化期间定义)。

P.S:但是要在生产环境中部署它,如果遇到任何意外问题,请在此处进行更新。

[1] http://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html