2

I'm currently working on a Java Application to connect to an Azure DB using JDBC. 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.

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. 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))

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. 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.

2 Answers2

3

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:

  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.

Alexander Gusev
  • 295
  • 1
  • 9
2

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. 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.

JNDI

Java provides an interface for your app to interact with directory/naming servers, without having to know the particular server at compile-time. That interface is called Java Naming and Directory Interface (JNDI).

Oracle provides a tutorial on JNDI, though it might be outdated nowadays. 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. Then you simply call getConnection method on that object. That method returns a Connection to your database through which you can do your JDBC work.

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.

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.

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. Leave that for later.

When starting out, just use a DataSource object to obtain your database connections throughout your codebase. Somewhere in your codebase, such as the startup of your app's lifecycle, hard-code a 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.

Your JDBC driver likely includes a DataSource implementation to use in your hard-coding. For example:

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154