django 在存储前加密文件

django encrypt files before storage

所以我想在存储到 django 之前加密文件并在检索时解密它们。

我正在为加密模块使用自定义存储 class。

import hashlib
import os
import uuid

import django.core.files.storage as storage
from cryptography.fernet import Fernet
from django.conf import settings
from django.core.files import File


class DefaultStorage(storage.FileSystemStorage):
    def __init__(self):
        super(DefaultStorage, self).__init__()
        self.encryptor = Fernet(settings.ENCRYPTION_KEY)

    def _save(self, name, content):
        encrypted = self.encryptor.encrypt(content.file.read())
        content.file.write(encrypted)
        print(content.file.read() == encrypted)
        return super(DefaultStorage, self)._save(name, content)

    def _open(self, name, mode='rb'):
        encrypted = open(self.path(name), mode).read()
        return File(self.encryptor.decrypt(encrypted))

    def get_available_name(self, name, max_length=None):
        # we return a hash of the file given,
        # in case we miss out on uniqueness, django calls
        # the get_alternative_name method
        dir_name, file_name = os.path.split(name)
        file_root, file_ext = os.path.splitext(file_name)

        file_root = hashlib.md5(file_root.encode()).hexdigest()
        name = os.path.join(dir_name, file_root + file_ext)
        return super(DefaultStorage, self).get_available_name(name, max_length)

    def get_alternative_name(self, file_root, file_ext):
        # we insert a random uuid hex string into the given
        # file name before returning the same back
        return '%s%s%s' % (file_root, uuid.uuid4().hex, file_ext)

我在这里覆盖了 _save_open 方法,但是 class 没有按预期工作。

在save方法下,我想加密文件的内容,但是打印的时候是这样的:

print(content.file.read() == encrypted)

它returns 错误。 这意味着文件甚至没有在一开始就被加密。我在这里做错了什么? _open 方法也一样吗?有人可以帮帮我吗?非常感谢!

编辑

    def _save(self, name, content):
        initial = content.file
        encrypted = self.encryptor.encrypt(content.file.read())
        content.file.write(encrypted)
        # the temporary file is already stored in the path
        # content.file.name
        # we need to write to this directory
        print(content.file.seek(0) == encrypted)
        return super(DefaultStorage, self)._save(name, content)

这个打印语句也是returns False

编辑 2

当我删除现有的 _open 方法时,我发现该文件仍然可以检索(无需解密)。这意味着该文件甚至没有被加密。知道为什么吗?有人可以帮我吗?

_save 方法:

def _save(self, name, content):
        encrypted = self.encryptor.encrypt(content.file.read())
        content.file.write(encrypted)
        return super(DefaultStorage, self)._save(name, content)

通常,content.file.read() 将光标留在文件末尾。

如果要再次读取文件,需要将光标移动到开头;否则,.read() 将只是 return 空,因为文件末尾后没有任何内容。

content.file.seek(0)                     # places cursor at the start
print(content.file.read() == encrypted)  # reads file again

这可以使用 content.file.seek(0)(将光标放在位置 0)或通过关闭并再次打开文件来完成。


但要小心,读取和写入同一个文件可能会很棘手并导致问题。而是写入辅助文件,然后用新文件替换原始文件。