django 在存储前加密文件

问题描述

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

我正在为相同的加密模块使用自定义存储类。

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,mode='rb'):
        encrypted = open(self.path(name),mode).read()
        return File(self.encryptor.decrypt(encrypted))

    def get_available_name(self,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 方法,但该类没有按预期工作。

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

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

它返回假。 这意味着该文件甚至没有在第一个地方被加密。我在这里做错了什么? _open 方法也一样?有人可以帮帮我吗?非常感谢!

编辑

    def _save(self,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,content)

此打印语句也返回 False

编辑 2

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

_save 方法

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

解决方法

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

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

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

这可以使用 content.file.seek(0)(将光标置于位置 0)来完成,也可以通过再次关闭和打开文件来完成。


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