I have a properties file containg the database username/password which i used it to manage ibatis connection with the database.
What is the best way to encrypt this properties file to be secure.
Actually I am using netbeans 6.8. Is there a way to encrypt this properties file while making packaging for the project, or any other way to prevent others to see the database credentials?
I am using ibatis to connect to database in a java desktop application
Any help would be appreciated.
thanks
Do you want to remove the temptation or make it impossible for the users to find the username/password to manually connect to the database?
If you just want to remove the temptation, you can off course encrypt the file. MyBatis (I see you tagged your question mybatis and ibatis so I'll assume MyBatis in my code) does not offer an out of the box way of using encrypted credentials, but you can intervene in code where the credentials are used and do your decryption there. You just have to create a custom data source factory.
Assuming you have a data source like this:
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://someServer/someDB" />
<property name="username" value="${user}" />
<property name="password" value="${password}" />
</dataSource>
with a properties file for the keys:
user=JohnDoe
password=p#$$word
you can encrypt the file and then create a custom data source factory like so (make sure you extend the right one: pooled, unpooled etc):
package com.test;
import java.util.Properties;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
public class CustomDataSourceFactory extends UnpooledDataSourceFactory {
#Override
public void setProperties(Properties properties) {
String user = null;
String pass = null;
// decrypt the file, use some fancy obfuscation, connect somewhere to get
// the username and password dynamically at startup, whatever...
//
// user = "JohnDoe";
// pass = "p#$$word";
properties.put("username", user);
properties.put("password", pass);
super.setProperties(properties);
}
}
Your data source will then change to:
<dataSource type="com.test.CustomDataSourceFactory">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://someServer/someDB" />
</dataSource>
And now the users can't see the credentials anymore.
But note that the above won't protect the username/password. Whatever you choose to eliminate the temptation (encryption, obfuscation, some sophisticated algorithm etc) the thing is that your user has everything he needs to reverse the process right there on his machine (decrypt key, extract the archive, decompile code, reverse engineering etc).
To make it impossible to retrieve the username/password, move iBatis/myBatis to an application server; i.e. transform your thick client into a thinner one. You obtain a decoupling between the windows application and the database. Your application server will run all the database queries based on commands received by the windows application.
In this case, the windows application will no longer be running the queries itself so it won't need the database credentials at all; the database credentials will be stored on the application server.
Are you using IBatis in a web application? If so, you should set up the database access details in the web container, not the application. Your application would then access the database via the container (Tomcat, GlassFish, Websphere etc.) and have no concern about security.
You basically want to set up a JNDI DataSource - something that exists in the container framework and not your application. I wouldn't want database access details in a properties file if I could help it.
Whatever you do, keep in mind, that to encrypt password, you need a key and you will have to store that key somewhere. That is the case for any solution you choose for encryption and applies to application server as well.
That means that key safety should be considered somehow, e.g. security can be setup on UNIX account level or something like that.
here is good example of the code which encrypts data and generates a key:
http://exampledepot.com/egs/javax.crypto/DesString.html
And here is how to save a load key from file:
http://www.java2s.com/Code/Java/Security/TripleDES.htm
I've also searching for same problem of securing Database.properties file and found an easy way:
If u know that the user of your application will be connected to the internet than without using encryption-decryption just host your properties file on any free file hosting site that can provide you with two major properties:
that can provide you direct link to the file.
and, that can provide you facilities to edit the same file whenever you want to change it.
One of the solution that i am using is Dropbox, You can watch a tutorial for using its public folder property Here
... Hope that will solve your problem as it solve mine :)
Related
Could you please tell me how we can provide encrypted password in the JNDI configuration and how we can decrypt that in the SPRING. In spring,
I see that we have to configure the datasource using
<bean id="DatabaseName" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/DatabaseName"/>
</bean>
but how we can override & decrypt the password in this, could you please help me
Thanks
Vivek
Your problem really has little to do with Spring - it is more like "How do I hide the database password".
One of the best methods is to create a datasource manually from the J2EE console. Weblogic and IBM Websphere support this, and automatically obfusticate the password. Your program then asks the container for a database connection, and need not supply the password. (There is an assumption that if you have deployment rights to the server, then you can connect freely to the server's datasources).
Tomcat is a bit more problematical. The datasource will be specified in ../conf/context.xml, and the password will be in plaintext. You need to use Unix file permissions to keep out those who should not know the password.
This answer How to hide database password in config file shows that this is a non-trivial problem.
I know it must be a very easy question, but I am new to java and find it hard to get exact code that I need. What I need to be able to do is to get currently logged in username from Windows and check whether this user belongs to the specific AD user group which needs to be defined in some config file. It is very easy to do in C#, but I have no idea how to do it in JAVA. Sample code would be great. In c# I would put security group into App.Config into app settings then I can grab Windows Identity of the currently logged in user and then iterate through all the groups user belongs to and match with desired. I need to do exactly the same in java
If you only care about the currently logged on Windows user (i.e., your Java program will be running on Windows) and don't mind using JNA, you can use the function supplied in platform.jar, Advapi32Util#getCurrentUserGroups() to get the groups that a user is a member of.
For example:
import com.sun.jna.platform.win32.Advapi32Util;
for (Advapi32Util.Account account : Advapi32Util.getCurrentUserGroups()) {
System.out.println(account.fqn);
}
This also takes advantage of the fact that Windows caches the users membership in all groups (including groups containing other groups the user is a member of) when the user logs on.
The requirements here seem kind of non-specific and this is starting to veer into areas that are probably not a great fit for SO, but I'll give it a go anyway.
Ultimately, where your system is going to be run determines how difficult the setup is going to be. If you are going to be running on a Windows-based server connected to the same domain you are authenticating with, then you should look at Waffle, which provides a servlet, a Spring Security filter, a JAAS plugin and a few other ways that you can implement Windows Integrated Authentication which uses native Windows methods to load the Windows identity and associated Active Directory groups. This will provide you with the experience most similar to using IIS and WIA with a .NET framework application. The down-side to this is that the server needs to be run on a Windows system.
Unfortunately, running in a non-Windows environment is going to require more setup and configuration. The most integrated solution is likely Spring Security which has a Kerberos extension capable of providing SPNEGO (Windows Integrated Authentication). The link above has the details (I believe they are still current) on what is necessary to get the Kerberos filter up and running. To access the group information, you would need to change the userDetailsService value in the example security.xml file. The easiest thing to do here would be to provide an appropriately configured LdapUserDetailsService as the object here. I'm not all that experienced with Spring, but it looks like the configuration would be something like (this is missing the contextSource).
<bean id="adUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg value="dc=domain,dc=com"/>
<constructor-arg value="(sAMAccountName={0})"/>
<constructor-arg ref="contextSource" />
</bean>
<bean id="adAuthoritiesPopulator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource"/>
<constructor-arg value="dc=domain,dc=com" />
<property name="groupSearchFilter" value="(member={0})"/>
<property name="rolePrefix" value="ROLE_"/>
<property name="searchSubtree" value="true"/>
<property name="convertToUpperCase" value="true"/>
</bean>
<bean id="userDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
<constructor-arg ref="adUserSearch"/>
<constructor-arg ref="adAuthoritiesPopulator"/>
</bean>
This should get you a Kerberos authenticated user with their associated groups.
If Spring Security isn't acceptable, you could try rolling your own version of this using perhaps Shiro and the pure-Java SPNEGO filter, but showing an example of that would require basically writing a program.
I hope this helps. Once you've decided on an approach, it's probably appropriate to address more specific questions as SO-type questions.
You can get all the groups without JNA like this:
String groups[] = (new com.sun.security.auth.module.NTSystem()).getGroupIDs();
Obviously this will work only on Windows, and even on Windows is the use of com.sun.* packages discouraged. See this for the explanation of the result.
This can be done through the Java SE APIs without using the com.sun.* packages directly. Use Java Authentication and Authorization Service (JAAS) (javax.security.auth.* and javax.security.auth.login.*) to access this information. Create a JAAS config file with the following entry:
sampleApp {
com.sun.security.auth.module.NTLoginModule required debug=false;
};
Save that entry as sampleapp_jaas.config. Next set the system property so Java will look for the config file.
-Djava.security.auth.login.config==sampleapp_jaas.config
Note that the double equals has special meaning. See the com.sun.security.auth.login.ConfigFile for details on the load order.
Then create LoginContext that will look for the entry in the JAAS config. Call login to populate the subject then access principals which represent the user groups.
LoginContext l = new LoginContext("sampleApp");
l.login();
try {
Subject s = l.getSubject();
for (Principal p : s.getPrincipals()) {
System.out.println(p);
}
} finally {
l.logout();
}
Using this setup, Java will use the com.sun.security.auth.module.NTSystem class to get the information but none of your code will be hardwired to the non-standard APIs.
I am working on a Java application using Hibernate.
I would like to deploy it on Elastic Beanstalk (Amazon Web Services) to be able to scale accordingly.
RDS is the database I want to use.
However, I do not know how to give my configuration settings to Elastic Beanstalk. Apparently it is now possible, without having to create an AMI and to use this AMI for each new server (when autoscaling).
I use :
hibernate.cfg.xml
server.xml (link to hibernate.cfg.xml)
But I want to scale easily, so no "manual configuration of EC2 instance" to input those files.
So how can I give those settings to my application without the two files ?
How to deploy on Elastic Beanstalk with those info ?
Amazon Relational Database Service (RDS) is a web service to setup relational databases in the cloud. RDS supports relational database engines such as MySQL, Oracle, SqlServer. For MySQL change the hibernate.cfg.xml like below
<session-factory>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property
name="connection.url">jdbc:mysql://my_sports_entertainment_db_url/news</property>
<property name="connection.username">my_username</property>
<property name="connection.password">my_password</property>
</session-factory>
Also check How to 'switch' from MySQL to Amazon RDS with minimal application impact?
I can see a way to do this, but it isn't pretty.
Your instance configuration file can include container commands. These run after the container and application are installed, but before the application is started. At this point, it is possible to edit the Tomcat context.xml file to add a datasource. The text you need to add is the usual datasource configuration. Your problem is that you have to do it from a script. The easiest thing might be to write the configuration and deliver it with your application, then use a container command to apply the mighty sed to splice it into the context.xml.
You have another problem in that the actual configuration you need to write must include things like the hostname, username, and password for RDS, which you won't have during development. AWS does expose these to Java through system properties, so the information must be on the machine somewhere. If you could find it, you could mix it into the configuration when you splice it into the context.xml.
Whilst this may be possible, as i said, it isn't pretty. It feels like a hack. There must be a better way of doing this.
If I have a database in a webserver(over the internet) and i have a java desktop application, in how many ways can i access that database. Please could you provide me with links for detailed article.
It depends on the database, but...
Most databases will allow you to access them remotely. You specify the URL and port when you set up your database connection in your Java program.
However, if you do not have control of the database, then this can be difficult. It is also a BIG security risk, unless you lock down the access via the HOSTS value of the user_id you are connecting with.
There are other work-around approaches, like VPNs, Tunnels and even fronting the database with a Web Service, but none of these are likely to give you the same level of access that the first option will.
Here is the link from oracle:
http://download.oracle.com/javase/tutorial/jdbc/index.html
Its very simple and easy to follow.
I recomend to use Hibernate, it easy to define any URL, to any database provider in Hibernate config file.
E.g
property name="driverClassName" value="com.mysql.jdbc.Driver"/>
property name="url" value="jdbc:mysql://189.234.223.89:3306/dbname"/>
property name="username" value="root"/>
property name="password" value="pwd"/>
Is there is any way to protect database password in -servlet.xml file using spring
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
<property name="url"><value>jdbc:mysql:///BUSINESS</value></property>
<property name="username"><value>root</value></property>
<property name="password"><value>password</value></property>
</bean>
Built-in, no. But you can check this blogpost which shows how to extend the DataSource to provide AES encryption of the passwords.
Another approach might be to extend PropertyPlaceholderConfigurer and handle the AES (or RSA) encryption of the properties.
However, as noted in the comments of the linked blogpost, having the cipher key stored in the same file does not add significant security - it only adds obfuscation. So in both approaches above you have to obtain the AES/RSA key from another location, possibly accessible only for the user under which your application server is started (this has to do with OS security).
The approach often taken for this is to have the password stored in an external properties file on the production machine. Access to this file can then be restricted.
See here for how to configure the spring part of this:
property-placeholder location from another property