如何防止MySQL用户名和密码反编译?

Java文件可以很容易地反编译。如果我必须使用代码中的登录数据,如何保护我的数据库?.class


答案 1

切勿将密码硬编码到代码中。最近在25个最危险的编程错误中提到了这一点

将秘密帐户和密码硬编码到您的软件中非常方便 - 对于熟练的逆向工程师来说。如果密码在所有软件中都相同,那么当密码不可避免地被知道时,每个客户都会变得容易受到攻击。而且因为它是硬编码的,所以修复起来非常痛苦。

应将配置信息(包括密码)存储在应用程序启动时读取的单独文件中。这是防止密码因反编译而泄漏的唯一真正方法(切勿将其编译为二进制文件)。

有关此常见错误的详细信息,可以阅读 CWE-259 文章。本文包含更全面的定义、示例以及有关该问题的许多其他信息。

在 Java 中,最简单的方法之一是使用 Preferences 类。它旨在存储各种程序设置,其中一些可能包括用户名和密码。

import java.util.prefs.Preferences;

public class DemoApplication {
  Preferences preferences = 
      Preferences.userNodeForPackage(DemoApplication.class);

  public void setCredentials(String username, String password) {
    preferences.put("db_username", username);
    preferences.put("db_password", password);
  }

  public String getUsername() {
    return preferences.get("db_username", null);
  }

  public String getPassword() {
    return preferences.get("db_password", null);
  }

  // your code here
}

在上面的代码中,您可以在显示用户名和密码的对话框询问后调用该方法。当您需要连接到数据库时,只需使用 and 方法来检索存储的值。登录凭据不会硬编码到二进制文件中,因此反编译不会带来安全风险。setCredentialsgetUsernamegetPassword

重要提示:首选项文件只是纯文本 XML 文件。确保采取适当的步骤来防止未经授权的用户查看原始文件(UNIX 权限、Windows 权限等)。至少在Linux中,这不是问题,因为调用将在当前用户的主目录中创建XML文件,无论如何,其他用户都无法读取该文件。在 Windows 中,情况可能有所不同。Preferences.userNodeForPackage

更多重要提示:在这个答案和其他人的评论中,有很多关于这种情况的正确架构是什么的讨论。最初的问题并没有真正提到使用应用程序的上下文,所以我将讨论我能想到的两种情况。第一种情况是,使用该程序的人已经知道(并被授权知道)数据库凭据。第二种情况是,作为开发人员,您试图对使用该程序的人保密数据库凭据。

第一种情况:用户有权知道数据库登录凭据

在这种情况下,我上面提到的解决方案将起作用。Java 类将以纯文本形式存储用户名和密码,但首选项文件只能由授权用户读取。用户只需打开首选项 XML 文件并读取登录凭据,但这不是安全风险,因为用户一开始就知道凭据。Preference

第二种情况:尝试对用户隐藏登录凭据

这是更复杂的情况:用户不应该知道登录凭据,但仍然需要访问数据库。在这种情况下,运行应用程序的用户可以直接访问数据库,这意味着程序需要提前知道登录凭据。我上面提到的解决方案不适合这种情况。您可以将数据库登录凭据存储在首选项文件中,但他的用户将能够读取该文件,因为他们将是所有者。实际上,确实没有以安全的方式使用此案例的好方法。

正确案例:使用多层体系结构

正确的方法是在数据库服务器和客户端应用程序之间有一个中间层,用于对各个用户进行身份验证,并允许执行一组有限的操作。每个用户都有自己的登录凭据,但数据库服务器没有登录凭据。凭据将允许访问中间层(业务逻辑层),并且对于每个用户都是不同的。

每个用户都有自己的用户名和密码,这些用户名和密码可以本地存储在首选项文件中,而不会有任何安全风险。这称为三层体系结构(层是数据库服务器、业务逻辑服务器和客户端应用程序)。它更复杂,但它确实是做这种事情的最安全的方法。

操作的基本顺序为:

  1. 客户端使用用户的个人用户名/密码通过业务逻辑层进行身份验证。用户名和密码是用户已知的,与数据库登录凭据没有任何关系。
  2. 如果身份验证成功,客户端将向业务逻辑层发出请求,要求从数据库中提供一些信息。例如,产品库存。请注意,客户端的请求不是 SQL 查询。它是一个远程过程调用,例如 。getInventoryList
  3. 业务逻辑层连接到数据库并检索请求的信息。业务逻辑层负责根据用户的请求形成安全的 SQL 查询。应清理 SQL 查询的任何参数以防止 SQL 注入攻击。
  4. 业务逻辑层将清单列表发送回客户端应用程序。
  5. 客户端向用户显示清单列表。

请注意,在整个过程中,客户端应用程序从不直接连接到数据库。业务逻辑层接收来自经过身份验证的用户的请求,处理客户端对清单列表的请求,然后才执行 SQL 查询。


答案 2

将密码放入应用程序将读取的文件中。切勿在源文件中嵌入密码。时期。

Ruby有一个鲜为人知的模块,称为DBI::D BRC用于这种用法。我毫不怀疑Java有一个等价物。无论如何,写一个并不难。