在 Java 中存储数据库密码(JDBC 连接字符串中需要)的最佳方式是什么?

What's the best way to store a Database Password (required in a JDBC connection string) in Java?

我目前正在开发一个 Java 应用程序以使用 JDBC 连接到 Azure 数据库。这就是我当前的代码的样子 -

File file = new File("filename.txt");
      Scanner scanner = new Scanner(file);
String pwd = scanner.nextLine();

String connectionUrl =
    "jdbc:sqlserver:{A link here};" +
    "database={DBName}; +
    "user={UserName};" +
    "password=" + pwd + ";"
    "encrypt=true;" +
    "trustServerCertificate=false;" +
    "hostNameInCertificate=*.database.windows.net;" +
    "loginTimeout=30;";

我打算在完成后在 Github 上公开上传这个项目,显然在那里设置纯文本密码似乎是个糟糕的主意。

但是,我不确定执行此操作的最佳方法是什么。我不认为存储散列密码会起作用,因为数据库字符串需要它以纯文本形式。我能想到的最好办法是将密码存储在文本文档中(连同其他几个 words/text),并使用 IO reader/substrings/BufferedReader 将其作为变量读取。这至少在某种程度上将它伪装成不经意的 reader,但是任何了解基本 Java 的人仍然能够识别它(或者只是简单地输入 System.out.print(pwd))

似乎应该有更好的方法,但我还没有找到任何可行的解决方案来阻止用户打开文本 document/conf 文件并读取密码。我想保持连接完全自动化,所以不想提示用户输入密码。 如果能回答如何实现这一点,我们将不胜感激!

我是一名(主要是自学成才的)学生,在 Java 方面的实践经验有限,如果我错过了一个相当明显的解决方案,我们深表歉意。

通常这些值存储在系统环境变量中。

例如设置如下系统变量:

  1. DATABASE_URL=<your url>
  2. DATABASE_NAME=<your database name>
  3. DATABASE_USER_NAME=<your database user name>
  4. DATABASE_USER_PASSOWRD=<your database user password>

然后在代码中使用 System.getProperty("DATABASE_URL") 等检索它们。 或者更好的方法是将所有连接 URL 存储在系统环境变量中:

  1. DATABASE_CONNECTION_URL=jdbc:sqlserver:someUrl...

您可以在 official documentation or .

中查看一些示例,了解如何在 Azure 中设置系统环境变量

外部化配置信息

最好的方法是外部化部署时配置信息。

通过外部化配置信息,您不再负责维护该信息。部署您的 Java 应用程序的 sysadmin 负有该责任。当发生更改时,例如将数据库移动到不同的服务器,或作为安全预防措施轮换密码,无需更改您的代码库,也不需要您作为程序员参与。

目录命名服务

有专门为此目的设计的服务器,通常称为 directory service or a name service. You have a choice of such servers, both open-source/free-of-cost and commercial. Such servers often comply with the LDAP 协议。

JNDI

Java 为您的应用程序提供了一个与 directory/naming 服务器交互的接口,而无需在编译时知道特定的服务器。该接口称为 Java Naming and Directory Interface (JNDI).

Oracle 提供了一个 tutorial on JNDI,尽管它现在可能已经过时了。可能仍然是一种很好的免费定向方式。

DataSource

对于数据库连接配置信息,您通常会使用 JNDI 为实现 DataSource interface. Then you simply call getConnection method on that object. That method returns a Connection to your database through which you can do your JDBC 工作的对象请求目录命名服务。

应用程序服务器

如果您正在构建 Jakarta EE 个应用程序,您的运行时容器(例如 Tomcat、Jetty、Glassfish、Payara、Wildfly、JBoss 等)可能会捆绑一个实现目录命名服务。

在运行时,应用服务器的系统管理员配置数据库服务器网络地址、网络端口号、数据库用户名和密码等连接信息。该配置信息封装在您通过 JNDI 获得的 DataSource 对象中。

开始使用

如果您刚刚开始构建应用程序,则无需立即设置 LDAP 服务器、配置 JNDI 等。留到以后再说。

开始时,只需使用 DataSource 对象来获取整个代码库中的数据库连接。在您的代码库中的某处,例如应用程序生命周期的启动,hard-code 一个 DataSource 对象。稍后,当您的应用程序接近完成时,您可以使用 JNDI 将硬编码的 DataSource 对象切换为软编码以获得 DataSource.

您的 JDBC driver 可能包含一个 DataSource 实现以用于您的硬编码。例如: