简体   繁体   English

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

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

I'm currently working on a Java Application to connect to an Azure DB using JDBC.我目前正在开发 Java 应用程序,以使用 JDBC 连接到 Azure DB。 This is what my current code looks like -这就是我当前的代码的样子 -

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;";

I intend to upload this project publicly on Github when complete, and it obviously seems like a terrible idea to have a plain-text password there.我打算在完成后在 Github 上公开上传这个项目,显然在那里有一个纯文本密码似乎是一个糟糕的主意。

However, I'm not sure what the best way to do this is.但是,我不确定最好的方法是什么。 I don't think storing a Hashed password would work, since the DB string requires it in plain-text.我不认为存储哈希密码会起作用,因为数据库字符串需要纯文本。 The best I could come up with was storing the password in a text document (along with several other words/text), and using the IO reader/substrings/BufferedReader to read it as a variable.我能想到的最好的办法是将密码存储在文本文档中(连同其他几个单词/文本),并使用 IO 阅读器/子字符串/BufferedReader 将其作为变量读取。 This at least somewhat disguises it to the casual reader, but anyone that knows basic Java will still be able to identify it (or just put a simple System.out.print(pwd))对于普通读者来说,这至少在某种程度上掩盖了它,但任何了解基本 Java 的人仍然能够识别它(或者只需输入一个简单的 System.out.print(pwd))

It does seem like there should be a better way, but I haven't found any workable solutions that prevent the user from just opening the text document/conf file and reading the password.似乎应该有更好的方法,但我还没有找到任何可行的解决方案来阻止用户打开文本文档/conf 文件并读取密码。 I would like to keep the connection completely automated, so wouldn't want to prompt the user to enter the password.我想保持连接完全自动化,所以不想提示用户输入密码。 Responses on how to achieve this would be appreciated!关于如何实现这一目标的回应将不胜感激!

I am a (largely self-taught) student with limited practical experience when it comes to Java, so apologies if I've missed a fairly obvious solution.在 Java 方面,我是一名(主要是自学成才的)学生,实践经验有限,所以如果我错过了一个相当明显的解决方案,我深表歉意。

Usually such values are stored in system environment variables.通常这些值存储在系统环境变量中。

For example, set following system variables:例如,设置以下系统变量:

  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>

Then in the code retrieve them by using System.getProperty("DATABASE_URL") etc. Or even better would be to store all connection URL in the system environment variable:然后在代码中使用System.getProperty("DATABASE_URL")等检索它们。或者更好的方法是将所有连接 URL 存储在系统环境变量中:

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

You can see some examples, how to set system environment variables in Azure in their official documentation or here on StackOverflow .您可以在官方文档StackOverflow 上查看一些示例,如何在 Azure 中设置系统环境变量。

Externalize config info外部化配置信息

The best way is to externalize deployment-time configuration information.最好的方法是将部署时配置信息外部化

By externalizing config info, you are not longer responsible for maintaining that info.通过外部化配置信息,您不再负责维护该信息。 The sysadmin deploying your Java app holds that responsibility.部署您的 Java 应用程序的系统管理员承担该责任。 When changes happen, such as moving the database to a different server, or rotating passwords as a security precaution, there is no need to alter your code base, and no need for you as a programmer to be involved.当发生更改时,例如将数据库移动到不同的服务器,或作为安全预防措施轮换密码,无需更改您的代码库,也无需您作为程序员参与。

Directory-Naming service目录命名服务

There are servers designed for this purpose, often referred to as a 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 protocol.此类服务器通常符合LDAP协议。

JNDI JNDI

Java provides an interface for your app to interact with directory/naming servers, without having to know the particular server at compile-time. Java 为您的应用程序提供了与目录/命名服务器交互的接口,而无需在编译时知道特定的服务器。 That interface is called Java Naming and Directory Interface (JNDI) .该接口称为Java 命名和目录接口 (JNDI)

Oracle provides a tutorial on JNDI , though it might be outdated nowadays. Oracle 提供了一个关于 JNDI 的教程,尽管它现在可能已经过时了。 Probably still a good free-of-cost way to get oriented.可能仍然是一种很好的免费获得方向的方式。

DataSource

For database connection configuration information, you would typically use JNDI to ask a directory-naming service for an object implementing the DataSource interface.对于数据库连接配置信息,您通常会使用 JNDI 向目录命名服务询问实现DataSource接口的 object。 Then you simply call getConnection method on that object.然后,您只需在该 object 上调用getConnection方法。 That method returns a Connection to your database through which you can do your JDBC work.该方法返回一个Connection到您的数据库,您可以通过它执行JDBC工作。

App servers应用服务器

If you are building Jakarta EE apps, your runtime container (such as Tomcat, Jetty, Glassfish, Payara, Wildfly, JBoss, and so on) likely bundles an implementation of a directory-naming service.如果您正在构建Jakarta EE应用程序,您的运行时容器(例如 Tomcat、Jetty、Glassfish、Payara、Wildfly、JBoss 等)可能会捆绑目录命名服务的实现。

At runtime, the sysadmin for the app server configures the connection information such as database server network address, network port number, and database user-name & password.在运行时,应用服务器的系统管理员配置数据库服务器网络地址、网络端口号、数据库用户名和密码等连接信息。 That configuration info is encapsulated within the DataSource object you obtain via JNDI.该配置信息封装在您通过 JNDI 获得的DataSource object 中。

Getting started入门

If you are just starting out in building your app, there is no need to immediately set up an LDAP server, configure JNDI, and so on.如果您刚刚开始构建应用程序,则无需立即设置 LDAP 服务器、配置 JNDI 等。 Leave that for later.留到以后。

When starting out, just use a DataSource object to obtain your database connections throughout your codebase.开始时,只需使用DataSource object 即可在整个代码库中获取数据库连接。 Somewhere in your codebase, such as the startup of your app's lifecycle, hard-code a DataSource object.在您的代码库中的某个地方,例如应用程序生命周期的启动,硬编码一个DataSource object。 Later, when your app nears completion, you can switch out that hard-coded DataSource object with soft-coding using JNDI to obtain the DataSource .稍后,当您的应用程序接近完成时,您可以切换出硬编码的DataSource object 并使用 JNDI 进行软编码以获取DataSource

Your JDBC driver likely includes a DataSource implementation to use in your hard-coding.您的JDBC 驱动程序可能包含用于硬编码的DataSource实现。 For example:例如:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM