问题描述
所以我想在 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
方法,但该类没有按预期工作。
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 文件,然后用新文件替换原始文件。