在Python开发中如何保护MySQL密码?

19 投票
4 回答
15993 浏览
提问于 2025-04-16 23:07

我正在写一个Python脚本,这个脚本会用到一个本地的MySQL数据库。这个程序会以源代码的形式交付出去。所以,MySQL的密码就会被大家看到。有没有什么好的办法来保护这个密码呢?

我的想法是,想办法阻止一些坏人查看源代码,直接访问MySQL,然后做一些……嗯,坏事。

4 个回答

0

这里有一个类似但没有答案的问题:https://stackoverflow.com/questions/2850710/connect-to-a-db-with-an-encrypted-password-with-django。Python的数据库API(PEP 249)并没有提供用加密或哈希密码连接数据库的接口,还是得用明文密码。

虽然其他编程语言有这个功能让人感觉安心,但实际上并没有提供额外的安全性:密码的哈希值和密码本身一样重要。你仍然需要控制对数据库资源的访问,正如exhuma所描述的那样

MySQL本身也没有提供额外的选项,无论你用不使用Python的绑定。你可以在MySQL用户手册的密码安全部分查看他们的指导。保护密码访问的推荐方法是把密码存储在一个选项文件中,并保护这个文件,正如glglgl所描述的那样

在那一页中:

你可以在运行客户端程序时指定密码的方法在这里列出,并对每种方法的风险进行了评估。简而言之,最安全的方法是让客户端程序提示输入密码,或者在一个适当保护的选项文件中指定密码。

7

在这种情况下,我在我的 .my.cnf 文件中创建一个新的部分,就像这样:

[files]
host=127.0.0.1
port=3307
database=files
default-character-set=utf8
password=foobar

然后在数据库初始化时使用它:

d=MySQLdb.connect(
    read_default_group='files',
    port=0,  # read from .my.cnf
    db='files',
    cursorclass=cursors.DictCursor,
    # amongst other stuff
)
19

简短回答

你不能。

如果密码存储在发给用户的文件里,你就必须认为它已经被泄露了!即使这个文件是编译后的程序,也总有办法(简单或复杂)去获取这个密码。

保护你的资源的唯一方法是只向用户开放有限的接口。你可以建立一个程序接口(比如REST、WS+SOAP、RMI、JavaEE+Servlets等),或者通过存储过程(SPROCs)只暴露数据库中的某些功能(见下文)。

先说一些事情...

这里的问题不应该是如何隐藏密码,而是如何保护数据库。记住,单靠密码往往保护力度很弱,不能只依赖它来保护数据库。你在使用SSL吗?没有?那么即使你在应用代码中成功隐藏了密码,网络上还是很容易被抓到!

你有多种选择,每种选择的安全性不同:

“应用角色”

为应用创建一个数据库用户,并为这个角色设置权限。一个很常见的设置是只允许进行增删改查(CRUD)操作。

优点

  • 设置非常简单
  • 防止执行 DROP 查询(比如SQL注入?)

缺点

  • 任何看到密码的人都可以访问数据库中的所有数据。即使这些数据在应用中通常是隐藏的。
  • 如果密码被泄露,用户可以在没有条件的情况下执行 UPDATEDELETE 查询(也就是说:可以一次性删除或更新整个表)。

原子认证

为每个应用用户创建一个数据库用户。这让你可以定义更细粒度的访问权限,比如按列来设置。例如:用户X只能选择表foo中的far和baz列,其他的都不能看。但用户Y可以 SELECT 所有内容,但不能更新,而用户Z则有完全的增删改查权限。

一些数据库允许你重用操作系统级别的凭证。这让用户的认证变得透明(只需登录工作站,这个身份就会转发到数据库)。在完整的微软技术栈中(操作系统=Windows,认证=ActiveDirectory,数据库=MSSQL)最容易实现,但我知道在其他数据库中也可以做到。

优点

  • 设置相对简单。
  • 权限控制非常细致。

缺点

  • 在数据库中设置所有访问权限可能会很繁琐。
  • 拥有 UPDATEDELETE 权限的用户仍然可能会不小心(或故意)在没有条件的情况下删除或更新数据。你可能会失去整个表中的所有数据。

使用存储过程的原子认证

在你的应用中不要写SQL查询。所有操作都通过存储过程来执行。然后为每个用户创建数据库账户,并只给存储过程分配权限。

优点

  • 最有效的保护机制。
  • 存储过程可以强制用户在每个查询中提供条件(包括 DELETEUPDATE)。

缺点

  • 不确定这是否适用于MySQL(我在这方面的知识有限)。
  • 开发周期复杂:你想做的每一件事,必须先在存储过程中定义。

最后的想法

你绝不能让应用执行数据库管理任务。大多数情况下,应用只需要的操作是 SELECTINSERTDELETEUPDATE。如果你遵循这个原则,用户发现密码的风险几乎没有。除了上面提到的那些点。

无论如何,记得备份。我想你是想保护你的数据库,免受意外删除或更新的影响。但意外总是会发生……记住这一点;)

撰写回答