Configuring MySQL DataSource in JavaEE without actual password - java

I am setting up my JavaEE environment as I have other times in the past. I have always placed the actual password in the DataSource config to access the database. I am wondering if it is prudent/possible/necessary to use a hashed value for the password instead of the actual. Or, is there some other, best practice, way of avoiding use of the actual password?
This may not even be a necessary precaution, but I am curious to know and Googling proved fruitless for me.
Here is how I have set things up in my META-INF --> context.xml in the past (with some settings omitted for simplicity):
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource
name="jdbc/mydatabasename"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://mydburl"
username="myusername"
password="actualpassword"
/>
</Context>
Basically, is there something else I can/should put in place of password="actualpassword" to make things more secure?

I don't think there's a standard way of doing this, but most vendors have implemented something, e.g. JBoss, Jetty or Glassfish.

Related

Modifying a JNDI connection pool programmaticaly

I am using Apache Tomcat JDBC connection pool library in my project and configured the context.xml file accordingly. My application instance needs to run at multiple locations, but load on the application will be different, so I want to modify the maxActive size and some other property based on the customer size at particular instance at runtime.
<Context path="/abc"
docBase="abc"
debug="5"
reloadable="false"
crossContext="true">
<Resource name="jdbc/abc"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="xxxxx"
url="xxxxxxx"
username="xxxxx" password="xxxxxx"
maxActive="20"
initialSize="0"
...
/>
</Context>
There is nothing special about a datasource created through JNDI: if you know its class (org.apache.tomcat.jdbc.pool.DataSource in your case), you can cast to that class and use the available setters to configure it:
private void customizeDataSource(final DataSource ds) {
if (ds instanceof PoolConfiguration) {
final PoolConfiguration poolConfig = (PoolConfiguration) ds;
poolConfig.setMaxActive(10);
}
}
(see the definition of PoolConfiguration). Implementations of javax.sql.DataSource also implement a very useful interface Wrapper, which may come handy if your code wraps the Tomcat JDBC datasource in something else:
private void customizeDataSource(final DataSource ds) throws SQLException {
if (ds.isWrapperFor(PoolConfiguration.class)) {
final PoolConfiguration poolConfig = ds.unwrap(PoolConfiguration.class);
poolConfig.setMaxActive(10);
}
}
There are however some problems that can arise from the programmatic approach above:
if you bundle tomcat-jdbc.jar with your application, only JNDI resources configured in your context.xml will be recognized by your code. Those in GlobalNamingResources will use the copy of org.apache.tomcat.jdbc.pool.DataSource bundled with Tomcat and will not match the instanceof condition.
if, on the other hand, you don't include tomcat-jdbc.jar into your WAR file, you must make sure that the parameters you set are supported by all versions of Tomcat on which your application will run.
You could try using standard JMX for this purpose.
As you can see in the documentation, Tomcat can expose the connection pool as a MBean object you can interact with using tools like JConsole, for instance.
The the MBean implementation basically delegates to the actual org.apache.tomcat.jdbc.pool.ConnectionPool the different operations that can be performed through the MBean interface and, AFAIK, ConnectionPool dynamically allocates connections based on current configuration.
ORIGINAL ANSWER BASED ON CONFIGURATION AND NOT RUNTIME BEHAVIOR
Please, consider review this related SO question and the self provided answer, I think it could be helpful.
Tomcat substitutes system provided environment variables in its configuration files:
Tomcat configuration files are formatted as schemaless XML; elements and
attributes are case-sensitive. Apache Ant-style variable substitution is
supported; a system property with the name propname may be used in a
configuration file using the syntax ${propname}. All system properties are
available including those set using the -D syntax, those automatically
made available by the JVM and those configured in the
$CATALINA_BASE/conf/catalina.properties file.
As indicated, the best way you could include the properties you need to dynamically being substituted by Tomcat is passing them as system properties using the -D option and probably in the JAVA_OPTS environment variable.
As indicated in the afore mentioned question, and advised as well in catalina.sh:
# Environment Variable Prerequisites
#
# Do not set the variables in this script. Instead put them into a script
# setenv.sh in CATALINA_BASE/bin to keep your customizations separate.
#
define them, for example, in a setenv.sh file located in the $CATALINA_BASE/bin directory.
For example:
#! /bin/sh
export MAX_ACTIVE_CONNECTIONS=20
export JAVA_OPTS="$JAVA_OPTS -DmaxActiveConnections=$MAX_ACTIVE_CONNECTIONS"
And use these properties in your XML configuration files:
<Context path="/abc"
docBase="abc"
debug="5"
reloadable="false"
crossContext="true">
<Resource name="jdbc/abc"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="xxxxx"
url="xxxxxxx"
username="xxxxx" password="xxxxxx"
maxActive="${maxActiveConnections}"
initialSize="0"
...
/>
</Context>
MySQL connects rapidly, thereby making connection pooling of limited use.
Usually, if there is a performance problem it is better handled by other techniques -- composite indexes, reformulating queries, working around optimization limitations of MySQL, etc.
Would you care to back up a step and let's analyze the bottlenecks?

Description of name="jdbc/project" in Context.xml?

I need some help with the Context.xml file in my Java Web Application in Netbeans.
My task was to get my Web App to connect to and display products from my SQL database. I got it to work but I really need help understanding this code:
<Resource auth="Container" driverClassName="com.mysql.jdbc.Driver"logAbandoned="true" maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/project" password="" removeAbandoned="true" removeAbandonedTimeout="60" type="javax.sql.DataSource" url="jdbc:mysql://localhost:3306/projinvoice?zeroDateTimeBehavior=convertToNull" username="root"/>
Could anyone tell me what name="jdbc/project" is? Where does this link to?
If I change the name then the Web App does not display my products. How did it get set to jdbc/project and where can I find it?
I did try and use Glassfish to create a JDBC Resource where I could have used that name but it does not show up?
Any help would be appreciated.
Regards
Context.xml is a configuration file for the container. Glassfish and Tomcat for example are using this file.
It declaratively configures the DataSource object in this case. At startup of the web-application, the container will instantiate this object and exposes it through JNDI.
JNDI is a mechanism to look for objects in the VM by name.
So somewhere on your web-app classes, this name is used to fetch this DataSource object. Have a search!

Explanation of context.xml

When using Tomcat, I've always treated web.xml as a kind of .htaccess or httpd.conf equivalent. It seems natural that there might have to be some way of configuring a web server.
However, I don't quite understand the purpose of context.xml. For instance, when working with JDBC, why do I have to add a resource-ref in web.xml and also a Resource with even more info in context.xml? Could I eliminate the context.xml file and somehow instantiate the DataSource in my code? I am asking because hypothetical examples like that help me understand.
EDIT: I am trying to understand what is happening in configs like this, in /META-INF/context.xml:
<Context>
<Resource name="jdbc/postgres" auth="Container" type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver" url="jdbc:postgresql://127.0.0.1:5432"
username="postgres" password="yes" maxActive="20" maxIdle="10"
maxWait="-1" />
</Context>
and, in WEB-INF/web.xml:
<resource-ref>
<description>postgreSQL Datasource example</description>
<res-ref-name>jdbc/postgres</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Why do I have to put both of those in there to use JDBC? What are they doing exactly and is there another way of doing the same thing but in the Java code? Like I said, not because I want to, but because I want to understand what they are doing better.
I don't quite understand the purpose of context.xml
context.xml is called from the web.xml through <context-param> tag. As you web.xml loads first when an application is created and it will create the references for the contexts that are configured in it.
I don't quite understand the purpose of context.xml
So, the purpose of context.xml is adding separation of codes. you can have separate contexts for different purposes . for example For Database connectivity, using other frameworks etc..,
Could I eliminate the context.xml file and somehow instantiate the DataSource in my code?
Yes ,you can do that by configuring the datasource in web.xml itself.
Hope this helps !!
To your initial questions:
I don't quite understand the purpose of context.xml
In Tomcat, you'll frequently see the term "Context". When you see this it's just referring to your application (i.e. Context == your web app). Thus /META-INF/context.xml is the configuration file specific to your application (actually, it's one of the configuration files because there are others).
For instance, when working with JDBC, why do I have to add a resource-ref in web.xml and also a Resource with even more info in context.xml?
You don't. You do not need to add anything to web.xml. If you define the resource in /META-INF/context.xml, Tomcat will create your resource and expose it through JNDI. You can then retrieve it as you would any resource from JNDI.
Could I eliminate the context.xml file and somehow instantiate the DataSource in my code?
Possibly. It's common to see Spring users create a DataSource in their Spring bean definitions. If you're not using Spring, you could still do it, but it would be more work.
Regardless of how you do this, if you setup the DataSource in your application you lose some flexibility. For example, you cannot share the DataSource across multiple applications and your application has to know how to set up the DataSource. If you define the DataSource in the server's configuration (i.e. with a Resource tag) then your application does not need this information.
To the response by san krish:
So, the purpose of context.xml is adding separation of codes. you can have separate contexts for different purposes . for example For Database connectivity, using other frameworks etc..,
The purpose of the Context tag is to configure the context (i.e. your application). It might provide you with the ability to pull certain aspects of your application, like the DataSource, out of the code and into configuration, but that's just the benefit of externalizing your configuration. It's not the purpose of this file.
Yes ,you can do that by configuring the datasource in web.xml itself.
No, with Tomcat you cannot configure a DataSource strictly through web.xml. It's just not possible to provide all of the information in web.xml that is required to create a DataSource. Because of this, you need to define a Resource tag for your DataSource and it is redundant to specify your DataSource in web.xml.

How does Tomcat load resources from context.xml

Hoping that someone can clear up a few things -
For a project I need to be able to switch between a Sybase and an Oracle database. Using Spring I have been to come up with a solution using AbstractRoutingDataSource to allow switching between the sybase and oracle data source as needed.
However, within my tomcat context.xml, I have listed all data sources - so for each one I have "jdbc/myDbSybaseDataSource" and "jdbc/myDbOracleDataSource". I was wondering, does tomcat attempt to create all of these data sources on start up, or does it wait until something in the code has invoked it?
I know in spring you can lazy load your beans, but would tomcat still create each resource in the context.xml anyways?
Any help is much appreciated!
Edit
The reason for asking is - if for example, the Sybase database is down, we need to know that we can switch to the Oracle, but Tomcat will not try and load the Sybase resource from the context.xml at start up (unfortunately I am not in a position to turn off one of the databases to test this! :) ).
From what I can tell, Tomcat is loading the resources - but not trying to actually connect to the database until part of the code invokes the data source, at which point Spring kicks in and does its work. It simply loads in the resources and keeps the info stored somewhere, when Spring tries to create the data source it looks up the corresponding resource info and uses this
Yes, Tomcat will create these datasources at startup. I cannot tell you how far this initialization goes but I would try to avoid any overhead that you dont need.
Do you need both datasources at runtime or is it just to be able to decide at startup of your application?
In the second case you can see the cotext.xml file as an (external) configuration file. You can then use springs jndi reference feature to connect to the desired database for the current application.
In the root-context.xml you reference ONE datasource by name:
<jee:jndi-lookup id="mvcDatasource" jndi-name="jdbc/mvcDatasource"
expected-type="javax.sql.DataSource" />
And depending on which type should be used you declare the correct implementation in the context.xml:
<Context>
<Environment name="configDirectory" type="java.lang.String" value="file:///tmp/app1" />
<Resource name="jdbc/mvcDatasource" type="javax.sql.DataSource" auth="Container" driverClassName="org.h2.Driver" maxActive="8" maxIdle="4" username="user" password="" url="jdbc:h2:file:/tmp/app1/db" />
</Context>
As you can see you can use other declarations too. In my case i inject the external config location here to be able to load properties files for the propertyconfigurer too. So this location will be application specific.

Tomcat war code visible?

I have a war file in which a class calls a MySQL DB from Java and thus has the MySQL login information in plain text in the source code. Obviously, for security resons, I don't want this visible to the outside world. The question is thus if the source code in a war file deployed on Tomcat is visible to the outside world?
It's not a problem but not flexible. More usefull to use JNDI. In context.xml put something like this:
<Resource
name="jndi_name_for_datasource"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
testOnReturn="true"
validationQuery="select 1 from dual"
timeBetweenEvictionRunsMillis="30000"
minIdle="1"
initialSize="1"
minEvictableIdleTimeMillis="30000"
username="solaris"
password="super"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:#localhost:1521:slife"
/>
and use lookup fo JNDI name
No it wont be visible. Provided there is no way to download war- Once war is downloaded- Anyone can locate the class and decompile it to see the password.
Better option would be to configure DataSoure - which is outside of your war.
But I think it is still a security issue, if anybody else is having access to tomcat server. e.g. other employees or administrators.
I would suggest you to add simple encryption/decryption technique in the code to prevent others to figure out the password.

Categories

Resources