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.
Related
Setting up an HTTP proxy for Java JVM 6.x isn't working for me; I'm hoping someone can spot what I'm missing.
I have a Java application deployed on JBOSS 5.1.2 that makes several calls to external web services. I'd like to be able to intercept these calls using a proxy: Fiddler version 4.4.8.0.
After doing an SO search I added the following flags to my JBOSS VM parameters at startup:
-DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=8888
I'm running JBOSS in IntelliJ 14.
I can see traffic from the browser to the application if I start JBOSS, Fiddler, and open the UI in Chrome. I do not see any calls from JBOSS to external services being intercepted. I thought I would see all the calls from JBOSS to external services in addition to those from the browser to JBOSS.
Update:
I tried adding these to properties-service.xml per this SO answer - no joy.
I'm running Spring 3, using Apache HttpClient as my web service client. I'm going to look into configuring proxy just for it.
Thanks to bmargulies and anyone else who looked at this. I have a solution that I hope will help someone else.
Adding -Dhttp.proxyHost parameters to my JVM startup options did nothing.
Adding those same parameters to JBOSS 5.1.2 configuration in my deployment properties-services.xml did nothing.
I believe that using Spring 3.x is a factor in explaining this behavior. I had to tell the Spring web service clients to use a proxy.
I added some Spring beans to wire in a Fiddler proxy HttpClient and injected that into the web service client, replacing the non-proxied version.
It failed the first time I tried it. It took me a while to figure out that the Apache Commons HttpConfiguration class didn’t follow the Java bean standard, so Spring blew up when it tried to wire it. I had to use the Spring MethodInvokingFactoryBean to get around it.
Here's the pertinent Spring configuration XML:
<!-- New beans for Fiddler proxy -->
<bean id="fiddlerProxyHost" class="org.apache.commons.httpclient.ProxyHost">
<constructor-arg name="hostname" value="localhost"/>
<constructor-arg name="port" value="8888"/>
</bean>
<bean id="fiddlerProxyHostConfiguration" class="org.apache.commons.httpclient.HostConfiguration"/>
<bean id="fiddlerProxyHostSetter" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="fiddlerProxyHostConfiguration"/>
<property name="targetMethod" value="setProxyHost"/>
<property name="arguments" ref="fiddlerProxyHost"/>
</bean>
<bean id="fiddlerProxyClient" class="org.apache.commons.httpclient.HttpClient">
<property name="hostConfiguration" ref="fiddlerProxyHostConfiguration"/>
</bean>
Now I can see the calls from the application to the web service in Fiddler. Joy!
Those parameters, first and foremost, are read by HttpURLConnection. They are specific to HTTP, of course, and so any other means of connecting to the outside world will necessarily ignore them.
There are many good reasons for code to avoid HttpURLConnection and just open a TCP connection through a plain old socket, even if that code plans to talk HTTP. HttpURLConnection has several 'browser emulation features' that get in the way. For example, it's broken for CORS and rejects some legitimate HTTP verbs.
Code that does that and in turn happens to do HTTP might choose to respect those parameters, and it might not. For example, I'm reasonably sure that the Apache Commons HTTP library gives the caller a choice.
If you put JBoss in a debugger and break on the socket connection primitives, I think you'll find out what's happening to you pretty quick in this respect.
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 :)
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
I've built a simple alert monitor to display the health of various applications. This is configured by XML, as each monitor instance needs to show different metrics. An example configuration may be:
<machine>
<monitors>
<check type="connectivity" name="Production Server">
<property key="host" value="ops01.corp" />
<alarm />
</check>
</monitors>
</machine>
Currently, I'm storing this in the root of the C:\ drive of the server. What would be nice is if I could put it in the deploy directory of the JBoss server, and could somehow get a reference to it. Is this possible? I looked at MBeans but it didn't seem to support complex XML structures.
Robert
Try JOPR - http://www.jboss.org/jopr .
For custom metrics, you can write your own plug-in.
You can get an input stream for any file in the classpath by using the ClassLoader#getResourceAsStream(String name) method. Just pass the location of the file relative to the classpath.