Depuis Rails 5.2, la méthode de cryptage par défaut pour ʻActiveSupport :: MessageEncryptor est passée de ʻaes-256-cbc
à ʻaes-256-gcm`. Cependant, en fonction du moment d'initialisation, une méthode de cryptage involontaire peut être utilisée, nous allons donc l'introduire.
Rails 5.2
Vérifiez avec les versions suivantes:
Tout d'abord, vérifiez la méthode de cryptage par défaut avec rails console
.
irb> encryptor = ActiveSupport::MessageEncryptor.new 'key'
=> #<ActiveSupport::MessageEncryptor:0x0000561c2eae8940 @secret="key", @sign_secret=nil, @cipher="aes-256-gcm", @aead_mode=true, @verifier=ActiveSupport::MessageEncryptor::NullVerifier, @serializer=Marshal, @options={}, @rotations=[]>
irb> encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"
Il s'avère que c'est certainement ʻaes-256-gcm`.
Dans une application réelle, il peut être utilisé en l'ayant dans un modèle.
app/models/some_model.rb
class SomeModel < ApplicationRecord
class << self
attr_reader :encryptor
def set_key(key)
@encryptor = ActiveSupport::MessageEncryptor.new key
end
end
set_key 'x' * 32
end
Vérifiez cela de la même manière.
irb> SomeModel.encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"
Semble bien.
Cependant, si le moment d'initialisation de MessageEncryptor
est trop tôt, la méthode de cryptage sera différente. Par exemple, si la constante SomeModel
est référencée dans le rappel ʻafter_initialize, elle sera automatiquement chargée à ce moment et un
MessageEncryptor` sera généré.
config/application.rb
class Application < Rails::Application
config.load_defaults 5.2
config.after_initialize do
SomeModel
end
end
irb> SomeModel.encryptor.instance_variable_get '@cipher'
=> "aes-256-cbc"
Il est devenu ʻaes-256-cbc au lieu de ʻaes-256-gcm
.
Le problème est le moment de refléter les paramètres de Rails.application.config.active_support.use_authenticated_message_encryption
. Ce paramètre est fourni pour la compatibilité avec les versions précédentes, et vous pouvez le redéfinir sur ʻaes-256-cbcen le définissant sur
false. Cette valeur de paramètre est la valeur par défaut «true» pour Rails 5.2, mais il semble que cette valeur de paramètre n'ait pas encore été reflétée au moment de l'exécution de «config.after_initialize». Par conséquent, s'il est initialisé à ce moment, il deviendra la valeur par défaut de
MessageEncryptor lui-même, ʻaes-256-cbc
.
Le code correspondant se trouve ici.
https://github.com/rails/rails/blob/v5.2.4.3/activesupport/lib/active_support/message_encryptor.rb#L88
Le problème étant que l'initialisation est trop précoce, il est possible de la retarder jusqu'au moment réel d'utilisation.
app/models/some_model2.rb
class SomeModel2 < ApplicationRecord
class << self
def set_key(key)
@key = key
end
def encryptor
@encryptor ||= ActiveSupport::MessageEncryptor.new @key
end
end
set_key 'x' * 32
end
config/application.rb
config.after_initialize do
SomeModel2
end
Vous pouvez maintenant utiliser ʻaes-256-gcm` dans la plupart des cas.
irb> SomeModel2.encryptor.instance_variable_get '@cipher'
=> "aes-256-gcm"
Cependant, si le timing lui-même lorsque vous voulez utiliser MessageEncryptor
est avant que le réglage de ʻuse_authenticated_message_encryptionne soit reflété, cela ne résout pas le problème. Dans ce cas, il est préférable de spécifier l'option
cipher:dans
MessageEncryptor.new`.
Rails 6
J'ai enquêté à nouveau avec la version suivante, mais il semble que la situation soit la même.
Un peu différent de 5.2 est que le chargeur automatique par défaut est Zeitwerk et il est déconseillé de charger automatiquement chaque modèle avec config / initializers / *. Rb
. Par conséquent, si vous vous référez par inadvertance au modèle avec config / initializers / *. Rb
, il peut être détecté avec un message d'avertissement. Cependant, comme dans l'exemple de cet article, il ne semble y avoir aucun avertissement dans config.after_initialize
.
Rails charge chaque fichier selon les besoins, mais le timing peut parfois être déroutant. Sachez que la synchronisation du chargement peut causer des problèmes.
Recommended Posts