【问题标题】:How to encrypt TextField before saving in database如何在保存到数据库之前加密 TextField
【发布时间】:2016-10-11 00:20:37
【问题描述】:

我正在尝试创建可以保存密码的模型,这里是我的模型:

class Server(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=20, null=True)
    hostname = models.CharField(max_length=50, null=True, blank=True)
    ip = models.GenericIPAddressField()
    ip2 = models.GenericIPAddressField(null=True, blank=True)
    user_name = models.CharField(max_length=20, null=True)
    password = models.TextField(max_length=500, null=True, blank=True)
    ssh_key = models.FileField(null=True, blank=True, upload_to='Keys/')

到目前为止,我阅读了很多博客和帖子,但我还没有找到任何将加密文本保存在数据库中的好方法

我正在尝试这种方法,但它也不适用于我,请查看下面的 View.py,

from cryptography.fernet import Fernet
class HostCreate(CreateView):
    model = Server
    template_name = 'inventory/host_create.html'
    form_class = HostForm

    # after getting POST data of fields (name, hostname, ip, pass, key) adding user and saving
    def form_valid(self, form):
        host = form.save(commit=False)
        host.user = User.objects.get(pk=self.request.user.pk)
        host.password = self.ecrypt(host.password)
        host.save()
        return redirect('inventory:hosts')

    def ecrypt(self, password): # need password and return cipher password
        key = 'wgjSSyfVKgz0EjyTilqeJSaANLDu7TzHKdpAXUeZPbM='
        cipher_suite = Fernet(key)
        cipher_text = cipher_suite.encrypt(password)
        return cipher_text 

这里出现错误,

Exception Type:     TypeError
Exception Value:    data must be bytes.
Exception Location:     /usr/lib64/python2.7/site-packages/cryptography/fernet.py in _encrypt_from_parts, line 55

密码字段是否有任何内置的 django 功能?

【问题讨论】:

    标签: django python-2.7 django-models django-admin


    【解决方案1】:

    您可以通过两种可能的方式做到这一点。

    1. 像这样为您的模型编写自定义保存方法

      class Server(models.Model):
          user = models.ForeignKey(User, on_delete=models.CASCADE)
          name = models.CharField(max_length=20, null=True)
          hostname = models.CharField(max_length=50, null=True, blank=True)
          ip = models.GenericIPAddressField()
          ip2 = models.GenericIPAddressField(null=True, blank=True)
          user_name = models.CharField(max_length=20, null=True)
          password = models.TextField(max_length=500, null=True, blank=True)
          ssh_key = models.FileField(null=True, blank=True, upload_to='Keys/')
      
          def save(self, *args, **kwargs):
              if not self.pk:
                  # encrypt_field_value_here
              super(Server, self).save(*args, **kwargs)
      
    2. 您可以使用自定义模型字段。您可以从here 获取有关此内容的文档。还要检查BaseEncryptedFieldhere

    您也可以使用this 包。

    【讨论】:

    • not self.pk 是什么意思?
    • 当前对象的主键。对于新对象,这将为 None。
    【解决方案2】:

    我通过使用 django-encrypted-fields Packages 解决了这个问题 步骤是:

    在项目根目录打开终端并执行命令。

    1. 安装包 django-encrypted-fields

      $ pip install django-encrypted-fields
      
    2. 创建一个基本的 keyczar 键集。在这种情况下为 AES-256。

      $ mkdir fieldkeys
      $ keyczart create --location=fieldkeys --purpose=crypt
      $ keyczart addkey --location=fieldkeys --status=primary --size=256
      
    3. 在你的 settings.py 中添加设置

      ENCRYPTED_FIELDS_KEYDIR = os.path.join(BASE_DIR, 'fieldkeys')
      
    4. 现在在 models.py 中

      from django.db import models
      import encrypted_fields
      class Server(models.Model):
          password = encrypted_fields.EncryptedCharField(max_length=500)
      

    更多详情请访问here

    希望这对将来的某人有所帮助

    【讨论】:

    • 当我尝试keyczart create --location=fieldkeys --purpose=crypt 我得到错误Missing parentheses in call to 'print'. Did you mean print("Generating private key sets...")?
    • @Aseem 那是因为你使用的是Python3,代码还不兼容Python3,如果你需要使用这个插件,请使用Python2
    【解决方案3】:

    对于密码字段,Django 使用自己的哈希。不过你可以change它。

    Django 中有一些加密方法。您可以像 AES 一样使用它们。它可以从加密密码中导入。

    否则你可以使用默认的Django Signer

    【讨论】:

      猜你喜欢
      • 2016-03-05
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多