This is my first post, so please be gentle.
I've recentley started using Powershell at work to change AD groups, find AD information etc. but I'm lacking the GUI that I like so much about Java.
Is there a simple way (or example of code) whereby I enter a target hostname and I'm returned with the details I ask for. AD memberhsip groups, account info etc?
My Java knowledge isn't as great as my Powershell so as much help as possible would be really apprechiated.
Thanks
If you are looking for a full java GUI to query Active-Directory, you may have a look to Apache Directory Studio.
If you want to query AD just using java, here is a sample code :
class TestAD
{
static DirContext ldapContext;
public static void main (String[] args) throws NamingException
{
try
{
System.out.println("Début du test Active Directory");
Hashtable<String, String> ldapEnv = new Hashtable<String, String>(11);
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
//ldapEnv.put(Context.PROVIDER_URL, "ldap://societe.fr:389");
ldapEnv.put(Context.PROVIDER_URL, "ldap://dom.fr:389");
ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
//ldapEnv.put(Context.SECURITY_PRINCIPAL, "cn=administrateur,cn=users,dc=societe,dc=fr");
ldapEnv.put(Context.SECURITY_PRINCIPAL, "cn=jean paul blanc,ou=MonOu,dc=dom,dc=fr");
ldapEnv.put(Context.SECURITY_CREDENTIALS, "pwd");
//ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
//ldapEnv.put(Context.SECURITY_PROTOCOL, "simple");
ldapContext = new InitialDirContext(ldapEnv);
// Create the search controls
SearchControls searchCtls = new SearchControls();
//Specify the attributes to return
String returnedAtts[]={"sn","givenName", "samAccountName"};
searchCtls.setReturningAttributes(returnedAtts);
//Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
//specify the LDAP search filter
String searchFilter = "(&(objectClass=user))";
//Specify the Base for the search
String searchBase = "dc=dom,dc=fr";
//initialize counter to total the results
int totalResults = 0;
// Search for objects using the filter
NamingEnumeration<SearchResult> answer = ldapContext.search(searchBase, searchFilter, searchCtls);
//Loop through the search results
while (answer.hasMoreElements())
{
SearchResult sr = (SearchResult)answer.next();
totalResults++;
System.out.println(">>>" + sr.getName());
Attributes attrs = sr.getAttributes();
System.out.println(">>>>>>" + attrs.get("samAccountName"));
}
System.out.println("Total results: " + totalResults);
ldapContext.close();
}
catch (Exception e)
{
System.out.println(" Search error: " + e);
e.printStackTrace();
System.exit(-1);
}
}
}
Related
I've been trying to get a simple snippet of code to run in java - authentication as binder to Foxpass (hosted LDAP service) and then trying to authenticate another user to it.
I basically created a binder in my Foxpass settings and created some users as well.
The code is:
Hashtable<String,String> env = new Hashtable <String,String>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, bindUser);
env.put(Context.SECURITY_CREDENTIALS, bindPassword);
env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
env.put(Context.PROVIDER_URL, myFoxpassUrl);
try {
DirContext ldapContext = new InitialDirContext(env);
NamingEnumeration<SearchResult> results = null;
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setCountLimit(1);
controls.setTimeLimit(5000);
String searchString = "(&(objectCategory=user)(sAMAccountName=username))";
results = ldapContext.search("", searchString, controls);
System.out.println(results.hasMore());
}
catch (Exception e)
{
e.printStackTrace()
}
The binding (authentication with bindUsername and bindPassword works well). However, searching for the users return 0 values. I tried using:
sAMAccountName=myusername
sAMAccountName=myusername#mydomain.com
sAMAccountName=CN=myusername,DC=mydomain,DC=com
Or
username=myusername
...
Or
Email=myusername#mydomain.com
But nothing seems to work. Any help on finding the right format to do the search.
Thank you
It seems to me your searchString once lived in an Active Directory environment. With Foxbase try
String searchString = String.format("(uid=%s)", username);
I followed this tutorial to search in active directory.
Sample code :
class SearchSubtree {
public static void main(String[] args) {
Hashtable<String, Object> env = new Hashtable<String, Object>(11);
env
.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");
try {
DirContext ctx = new InitialDirContext(env);
String[] attrIDs = { "sn", "telephonenumber", "golfhandicap", "mail" };
SearchControls ctls = new SearchControls();
ctls.setReturningAttributes(attrIDs);
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String filter = "(&(sn=Geisel)(mail=*))";
NamingEnumeration answer = ctx.search("", filter, ctls);
// Print the answer
ctx.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
But NameNotFoundException is thrown at
NamingEnumeration answer = ctx.search("", filter, ctls);
But when I pass, "DC=extldap,DC=com" as first argument, code works fine.
Is there any issue with the tutorial? Can first argument not be empty string? Or is this a limitation with Active Directory?
Generally speaking, for LDAP servers you always need a root context to start your search from. Basically, you are doing the equivalent of trying to search a SQL database without specifying a database or table name.
Some server implementations may allow an empty context (I know iPlanet used to allow it in some cases) but these are exceptions to the rule.
The javadoc for DirContext.search() says:
Searches in the named context or object for entries that satisfy the
given search filter. Performs the search as specified by the search
controls.
See search(Name, String, SearchControls) for details.
Parameters:
name the name of the context or object to search
...
Usually, in Active Directory it is fine to start searching from the domain root, which is always DC=<your>,DC=<domain>.
That is why your second search works.
I have been stuck at a point for so long. I am trying to authenticate a user from an LDAP directory using LDAP via JNDI, but the code attached below returns nothing for "results" i.e. the search method (marked with **) returns null. I tried to debug the code, but did not understand what exactly is going on behind the "search" function of "DirContext" class. Can anybody help please?
public class Authenticate {
#SuppressWarnings({ "unchecked", "rawtypes", "unused" })
public static void main(String[] args) throws NamingException {
final String ldapAdServer = "ldap://iauth.tum.de:389/cn=someuser,ou=users,ou=data,ou=prod,ou=iauth,dc=tum,dc=de";
final String ldapUsername = "cn=someuser,ou=users,ou=data,ou=prod,ou=iauth,dc=tum,dc=de";
final String ldapPassword = "somepassword";
Hashtable env = new Hashtable();
env.put(Context.SECURITY_AUTHENTICATION, "none");
if(ldapUsername != null) {
env.put(Context.SECURITY_PRINCIPAL, ldapUsername);
}
if(ldapPassword != null) {
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
}
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapAdServer);
DirContext ctx = new InitialDirContext(env);
NamingEnumeration<SearchResult> results = null;
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
**results = ctx.search("", "(objectClass=Person)", controls);**
while (results.hasMoreElements())
{
SearchResult searchResult = (SearchResult) results.next();
Attributes attributes = searchResult.getAttributes();
Attribute attr = attributes.get("cn");
}
}
}
Since the search method of "DirContext" (marked in **), returns nothing, I can never enter the while loop. Can anybody tell where exactly I am being wrong.
You appear to be searching an Active Directory instance. If that's the case (and even if it's not the issue may be the same), then the problem is not to do with your search code but with the initial setup. In particular, this line is at fault:
env.put(Context.SECURITY_AUTHENTICATION, "none");
Per the documentation, setting SECURITY_AUTHENTICATION to "none" performs an anonymous bind, meaning that to the LDAP directory your search request appears to be coming from an anonymous user. By default, Active Directory does not return an error when it gets an anonymous bind request, but the anonymous user does not normally have permissions to search the directory. To ensure that your context is created and bound to the appropriate identity, you should change the line in question to:
env.put(Context.SECURITY_AUTHENTICATION, "simple");
Or even not set the SECURITY_AUTHENTICATION parameter at all, since it defaults to "simple".
Change your filter to "(objectClass=*)" and see, otoh, you are using JNDI not Apache LDAP API like you mentioned in the question.
i am trying to search user in users directory(ou=users,ou=system), but i am not getting result plz help me out.
following is my code for search users directory
public void search(String uid) {
String searchBase = "ou=users,ou=system";
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, url);
env.put(Context.SECURITY_CREDENTIALS, rootpass);
DirContext ctx = null;
try {
![enter image description here][1] // Create the initial directory context
ctx = new InitialDirContext(env);
// Create the search controls
SearchControls searchCtls = new SearchControls();
// Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchCtls.setReturningAttributes(new String[] { "uid", "cn" });
String searchFilter =" (uid="+uid+") ";//"(objectclass=*)"; //" (uid="+uid+") ";
// initialize counter to total the results
int totalResults = 0;
// Search for objects using the filter
NamingEnumeration answer = ctx.search(searchBase, searchFilter,
searchCtls);
while (answer.hasMore()) {
SearchResult sr = (SearchResult) answer.next();
totalResults++;
System.out.println(">>>" + sr.getName());
System.out.println(">>>");
}
} catch (NamingException e) {
e.printStackTrace();
}
}
and here is my directory structure
You might want to look at this sample.
If "nothing is printed but when I search in any other directory it works fine", the possibilities boil down to:
you are failing to connect to the LDAP directory at all
your search base is wrong
your filter is wrong
the record you're searching for does not exist
the credentials you're using to bind don't have permissions to search in that location
Some of those will throw a NamingException, but others (like "record does not exist" or "no permission to search") will simply return no results.
As far as the User folder goes, the answer is in another post LDAP Directory Entry in .Net - not working with OU=Users
This may seem silly and stupid, but the default tree setup in Active Directory is not OU=Users,dc=domain,dc=com but rather CN=Users,dc=domain,dc=com (Note the CN= not the OU= for Users.
I have directory context for LDAP but i need to find out the BASE DN from that
directory context object.
I have following code to get Directory context object,
// Configure our directory context environment.
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://test.mycomp.com:389");
env.put(Context.SECURITY_AUTHENTICATION, "Simple");
env.put(Context.SECURITY_PRINCIPAL,"uid=test.gen,OU=Generics,O=test.mycomp.com");
env.put(Context.SECURITY_CREDENTIALS, "test123");
DirContext dirContext = new InitialDirContext(env);
System.out.println("loaded dirContext");
I have following code to get the Base DN,
I has been returning base DN name but i want to make my filter optimised rather than putting 2 loops to get base DN,
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.OBJECT_SCOPE);
NamingEnumeration results = dirContext.search("",
"(&(objectClass=organization)(objectClass=top))", constraints);
// Fail if no entries found
if (results == null || !results.hasMore()) {
System.out.println("No result found");
return;
}
while(results.hasMoreElements()){
Object res = results.next();
SearchResult serResult = (SearchResult) res;
Attributes atts = serResult.getAttributes();
System.out.println(atts.toString());
Attribute baseAttr = atts.get("namingContexts");
NamingEnumeration ids = baseAttr.getAll();
while(ids.hasMoreElements()){
Object obj = ids.next();
System.out.println(obj.toString());
}
}
Please help me out to optimize my filter.
You don't need the search. Just get the namingContexts attribute from the InitialContext.
Attributes atttrs = context.getAttributes("", new String[]{"namingContexts"});
LDAP-compliant directory servers should provide information about the namingContexts when the root DSE is queried. For more information about the root DSE, see "LDAP: The root DSE". The UnboundID LDAP SDK provides a class to encapsulate the root DSE and a convenience method to retrieve it.