модуль ActiveRecord::Encryption::EncryptableRecord
Этот модуль подключается к моделям Active Record, чтобы сделать их пригодными для шифрования. Он добавляет объявление атрибутов encrypts, а также API для шифрования и расшифровки записей.
Константы
- ORIGINAL_ATTRIBUTE_PREFIX
Открытые методы экземпляра
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 132
def add_length_validation_for_encrypted_columns
encrypted_attributes&.each do |attribute_name|
validate_column_size attribute_name
end
end # File activerecord/lib/active_record/encryption/encryptable_record.rb, line 157
def ciphertext_for(attribute_name)
if encrypted_attribute?(attribute_name)
read_attribute_before_type_cast(attribute_name)
else
read_attribute_for_database(attribute_name)
end
end Возвращает шифротекст для attribute_name.
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 171 def decrypt decrypt_attributes if has_encrypted_attributes? end
Расшифровывает все атрибуты, поддерживающие шифрование, и сохраняет изменения.
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 58
def deterministic_encrypted_attributes
@deterministic_encrypted_attributes ||= encrypted_attributes&.find_all do |attribute_name|
type_for_attribute(attribute_name).deterministic?
end
end Возвращает список атрибутов, шифруемых детерминированным способом в классе модели.
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 166 def encrypt encrypt_attributes if has_encrypted_attributes? end
Шифрует все атрибуты, поддерживающие шифрование, и сохраняет изменения.
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 84
def encrypt_attribute(name, key_provider: nil, key: nil, deterministic: false, support_unencrypted_data: nil, downcase: false, ignore_case: false, previous: [], compress: true, compressor: nil, **context_properties)
encrypted_attributes << name.to_sym
decorate_attributes([name]) do |name, cast_type|
scheme = scheme_for key_provider: key_provider, key: key, deterministic: deterministic, support_unencrypted_data: support_unencrypted_data, \
downcase: downcase, ignore_case: ignore_case, previous: previous, compress: compress, compressor: compressor, **context_properties
ActiveRecord::Encryption::EncryptedAttributeType.new(scheme: scheme, cast_type: cast_type, default: columns_hash[name.to_s]&.default)
end
preserve_original_encrypted(name) if ignore_case
ActiveRecord::Encryption.encrypted_attribute_was_declared(self, name)
end # File activerecord/lib/active_record/encryption/encryptable_record.rb, line 146 def encrypted_attribute?(attribute_name) name = attribute_name.to_s name = self.class.attribute_aliases[name] || name return false unless self.class.encrypted_attributes&.include? name.to_sym type = type_for_attribute(name) type.encrypted? read_attribute_before_type_cast(name) end
Возвращает признак того, зашифрован ли указанный атрибут.
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 49
def encrypts(*names, key_provider: nil, key: nil, deterministic: false, support_unencrypted_data: nil, downcase: false, ignore_case: false, previous: [], compress: true, compressor: nil, **context_properties)
self.encrypted_attributes ||= Set.new # not using :default because the instance would be shared across classes
names.each do |name|
encrypt_attribute name, key_provider: key_provider, key: key, deterministic: deterministic, support_unencrypted_data: support_unencrypted_data, downcase: downcase, ignore_case: ignore_case, previous: previous, compress: compress, compressor: compressor, **context_properties
end
end Шифрует атрибут name.
Параметры
-
:key_provider— поставщик ключей для предоставления ключей шифрования и расшифровки. По умолчанию используетсяActiveRecord::Encryption.key_provider. -
:key— пароль, из которого выводится ключ. Это сокращённая форма:key_provider, предоставляющего производные ключи. Нельзя использовать оба параметра одновременно. -
:deterministic— по умолчанию шифрование не является детерминированным. Для каждой операции шифрования используется случайный вектор инициализации. Это означает, что шифрование одного и того же содержимого одним и тем же ключом дважды создаст разные шифротексты. Если задать значениеtrue, вектор инициализации будет сформирован на основе зашифрованного содержимого. Это означает, что одинаковое содержимое будет создавать одинаковые шифротексты. Это позволяет выполнять запросы к зашифрованному тексту с помощью Active Record. По умолчанию при детерминированном шифровании новые данные шифруются по самой старой схеме шифрования. Это можно изменить, задавdeterministic: { fixed: false }. В этом случае для шифрования новых данных будет использоваться самая новая схема шифрования. -
:support_unencrypted_data— если значение равно true, незашифрованные данные можно читать обычным образом. Если значение равно false, будут возникать ошибки. Если значение не задано, используетсяconfig.active_record.encryption.support_unencrypted_data. Это полезно, когда вы шифруете один столбец и хотите отключить поддержку незашифрованных данных, не меняя глобальную настройку. -
:downcase— если значение равно true, зашифрованное содержимое автоматически преобразуется в нижний регистр. Это позволяет игнорировать регистр при запросах к данным. Обратите внимание: регистр будет утрачен. Чтобы сохранить его, используйте:ignore_case. -
:ignore_case— если значение равно true, параметр работает как:downcase, но также сохраняет исходный регистр в специально предназначенном столбце +original_<name>+. При чтении зашифрованного содержимого возвращается вариант с исходным регистром. При этом можно выполнять запросы без учёта регистра. Этот параметр можно использовать, только если:deterministicимеет значение true. -
:context_properties— дополнительные свойства, переопределяющие настройкиContextпри шифровании и расшифровке этого атрибута. Например:encryptor:,cipher:,message_serializer:и т. д. -
:previous— список предыдущих схем шифрования. Если он задан, схемы будут проверяться по порядку при попытке прочитать атрибут. Каждая запись списка может содержать свойства, поддерживаемыеencrypts. Кроме того, при использовании детерминированного шифрования эти схемы будут применяться для создания дополнительных шифротекстов, проверяемых в запросах.
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 78
def global_previous_schemes_for(scheme)
ActiveRecord::Encryption.config.previous_schemes.filter_map do |previous_scheme|
scheme.merge(previous_scheme) if scheme.compatible_with?(previous_scheme)
end
end # File activerecord/lib/active_record/encryption/encryptable_record.rb, line 109
def override_accessors_to_preserve_original(name, original_attribute_name)
include(Module.new do
define_method name do
if ((value = super()) && encrypted_attribute?(name)) || !ActiveRecord::Encryption.config.support_unencrypted_data
send(original_attribute_name)
else
value
end
end
define_method "#{name}=" do |value|
self.send "#{original_attribute_name}=", value
super(value)
end
end)
end # File activerecord/lib/active_record/encryption/encryptable_record.rb, line 98
def preserve_original_encrypted(name)
original_attribute_name = "#{ORIGINAL_ATTRIBUTE_PREFIX}#{name}".to_sym
if !ActiveRecord::Encryption.config.support_unencrypted_data && !column_names.include?(original_attribute_name.to_s)
raise Errors::Configuration, "To use :ignore_case for '#{name}' you must create an additional column named '#{original_attribute_name}'"
end
encrypts original_attribute_name
override_accessors_to_preserve_original name, original_attribute_name
end # File activerecord/lib/active_record/encryption/encryptable_record.rb, line 70
def scheme_for(key_provider: nil, key: nil, deterministic: false, support_unencrypted_data: nil, downcase: false, ignore_case: false, previous: [], **context_properties)
ActiveRecord::Encryption::Scheme.new(key_provider: key_provider, key: key, deterministic: deterministic,
support_unencrypted_data: support_unencrypted_data, downcase: downcase, ignore_case: ignore_case, **context_properties).tap do |scheme|
scheme.previous_schemes = global_previous_schemes_for(scheme) +
Array.wrap(previous).collect { |scheme_config| ActiveRecord::Encryption::Scheme.new(**scheme_config) }
end
end # File activerecord/lib/active_record/encryption/encryptable_record.rb, line 65 def source_attribute_from_preserved_attribute(attribute_name) attribute_name.to_s.sub(ORIGINAL_ATTRIBUTE_PREFIX, "") if attribute_name.start_with?(ORIGINAL_ATTRIBUTE_PREFIX) end
Для заданного имени атрибута возвращает имя исходного атрибута, если атрибут является сохранённым.
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 138
def validate_column_size(attribute_name)
if limit = columns_hash[attribute_name.to_s]&.limit
validates_length_of attribute_name, maximum: limit
end
end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.