首页 > 解决方案 > 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, 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)

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

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

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

它返回假。这意味着文件甚至没有被加密。我在这里做错了什么?方法一样_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)

此打印语句也返回 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)

标签: djangodjango-storagepython-cryptography

解决方案


通常,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)或通过关闭并再次打开文件来完成。


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


推荐阅读