【问题标题】:how to securely store a password for a 3rd party service in django?如何在 django 中安全地存储 3rd 方服务的密码?
【发布时间】:2013-04-24 13:07:06
【问题描述】:

我在 Django 上运行一个网络服务。用户注册到我的系统并为我提供第三方网络服务的登录详细信息(用户名和密码)。

我的目的是以最好和最安全的方式存储这些详细信息。 不幸的是,我的服务需要这些数据用于查询 3rd 方服务的一些离线脚本,因此我无法存储使用用户密码加密的登录名/密码(并将其用于解密它们的密钥。

我阅读了很多关于 stackoverflow 的文章,但其中大多数(例如:What is the best way to store password in database when API call requires sending of password in plain text?)不需要“离线”访问这些数据。

我唯一的想法是将这些详细信息存储在一个非常安全的服务器上,该服务器只接受来自我的 django 服务器的请求,并通过 tls 进行通信。

您还有其他想法吗?

提前谢谢你!

【问题讨论】:

  • 您将要寻找的第三方服务是否具有 Oauth?无论您使服务器之间的通信多么安全,它在概念上都是不安全的(不幸的是,它不能变得更安全)。 Oauth 解决了所有这些问题。
  • 很遗憾,这项服务没有 Oauth。

标签: django encryption passwords password-protection password-encryption


【解决方案1】:

首先,其他文章是正确的:永远不要以纯文本形式存储密码。如果您得出需要以纯文本形式存储它们的结论,则需要重新考虑您的策略(Oauth?)。使用带盐的散列密码的全部原因是,即使出现问题,密码也是安全的(因为没有密码,只有散列......)。我实际上想知道您究竟出于什么原因需要这些第三方用户名和密码?

如果您确实必须存储这些,请使用加密文件或数据库字段并设置它,以便每当您的脚本运行时,您都需要手动输入解密密码。我在这里假设您不是每 5 分钟运行一次此脚本,而是每周运行一次。除此之外,请绝对确保执行此操作的服务器没有做任何其他事情并且没有其他本地用户,否则可能会分析内存并找到解密的密码。

总而言之,我仍然会说你正在尝试的事情非常非常危险,你应该非常小心地进行......

【讨论】:

  • 我的 Web 服务分析来自此第 3 方服务的数据并将结果显示给用户。我需要运行多个分析,这就是我离线运行它们的原因。当用户登录我的系统时,会显示结果。我运行的分析需要从 3rd 方服务中检索一些数据。
【解决方案2】:

这是一个旧的方法,但要走的路是在存储密码之前对其进行加密。使用安全存储的密钥(即不在数据库中(或至少不在同一个数据库中)并且不在 Github 中)并将其加载到部署项目的环境中。这样,任何直接访问数据库的人都无法读取密码。

possible source of more info

Cryptography library 很好用,在上面的文章中有引用。

对于这个问题中描述的情况,我会在环境中放置一个加密密钥并在部署时将其加载到settings.py,它看起来像这样:

生成密钥

from cryptography.fernet import Fernet

key = Fernet.generate_key()

如果库已安装到您的 Python 环境中,您可以在 Python 控制台中运行上述代码。

根据您部署应用程序的方式,您需要提供对其密钥的访问权限。以下是将其引入您的环境的一种方法:

export ENCRYPTION_KEY="<key>"

一旦你在你的环境中设置了它,添加这一行

ENCRYPTION_KEY=os.get("ENCRYPTION_KEY")

如何使用密钥?根据您的设置,您可以在模型上编写其他属性方法来获取和设置字段的值,例如

 class mymodel(models.Model):
    
  ....
  @property
  def password(self):
      f = Fernet(settings.ENCRYPTION_KEY)
      password = f.decrypt(self.<myfield>)
      return password

  @password.setter
  def password(self, password):
      f = Fernet(settings.ENCRYPTION_KEY)
      token = f.encrypt(<password>)
      self.<myfield> = token
      self.save()

其他选项可能是子类化另一个 django 模型字段并在那里添加功能。如果你只在一个地方这样做,那么上面应该没问题。

如何存储加密密钥取决于您,环境只是一种选择。这里的关键是将它保存在安全的地方,重要的是不要丢失它......或者祝你好运;)

【讨论】:

    猜你喜欢
    • 2012-01-12
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    相关资源
    最近更新 更多