I did an LDAP Directory Search and received some results. I need to iterate over these results and display the Dn for each entry.
In my test environment I returned the Dn value by obtaining the value of the entryDN attribute.
In the production environment the entryDN attribute always returns null.
In both environments when I return the value of the Dn attribute all I get is null.
What I really need to do is reliably obtain the Dn from any environment.
Suggestions?
To reliably get the Dn use the method SearchResult.getNameInNamespace();
Building on user2135970's answer, it's not pretty to mix JNDI with Spring LDAP, but it can be done:
private String getDistinguishedName(String addtlFilter) throws NamingException {
String dn = null;
LdapContextSource contextSource = (LdapContextSource) ldapTemplate.getContextSource();
SearchControls ctrls = new SearchControls();
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
DirContext dc = null;
try {
dc = ldapTemplate.getContextSource().getContext(contextSource.getUserDn(), contextSource.getPassword());
final String filter = String.format("(&(%s)%s)", addtlFilter, searchFilter);
NamingEnumeration<SearchResult> results = dc.search(searchBase, filter, ctrls);
if (results.hasMore()) {
dn = results.next().getNameInNamespace();
}
} finally {
if (dc != null) {
dc.close();
}
}
return dn;
}
Related
I am trying to fetch some users from Active Directory group and update them in another one of our site.
The task is almost done except for the part where I need to fetch the user ID from NamingEnumeration and pass it onto another method which will update it through a REST API call. Below is a part of the code where I am fetching users from AD group:
DirContext myContext = new InitialDirContext(envVars);
SearchControls searchCtrls = new SearchControls();
searchCtrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String[] attributes = { "cn", "member"};
searchCtrls.setReturningAttributes(attributes);
String filter = "(&(objectClass=group)(cn=GROUP_NAME))";
NamingEnumeration values = myContext.search("DC=XXXX,DC=XXXX",filter,searchCtrls);
while (values.hasMoreElements())
{
SearchResult result = (SearchResult) values.next();
Attributes attribs = result.getAttributes();
if (null != attribs)
{
for (NamingEnumeration ae = attribs.getAll(); ae.hasMoreElements();)
{
Attribute atr = (Attribute) ae.next();
String attributeID = atr.getID();
for (
Enumeration vals = atr.getAll();
vals.hasMoreElements();
System.out.println(attributeID+": "+vals.nextElement())
);
}
}
}
When I run this, the output is something like below:
member: CN=USERNAME,OU=XXX,OU=XXX,OU=XXX,DC=XXX,DC=XXX,DC=XXX
member: CN=USERNAME,OU=XXX,OU=XXX,OU=XXX,DC=XXX,DC=XXX,DC=XXX
Basically, I need to fetch this CN i.e. USERNAME alone, which I will pass onto another method.
I did try to get them in a String array and process them, to no avail and I am running short of time.
Any ideas would be greatly appreciated. Thanks.
Well, I did get around this problem.
Below approach worked for me.
if (null != attribs)
{
for (NamingEnumeration ae = attribs.getAll(); ae.hasMoreElements();)
{
Attribute atr = (Attribute) ae.next();
for (
Enumeration vals = atr.getAll();
vals.hasMoreElements();
) {
list.add(vals.nextElement().toString());
}
}
}
I let the output inside a list and clipped the unwanted parts to obtain the CN alone.
Would be glad if this helps someone in the future.
When I try to search records by using query (testAtt=1) in Apache Directory Studio they showing me 17062 records and when I run the same query on my Java code they get only 8531 records. My Java Code is given below
String searchFilter = propFile.getProperty(Constants.GetAllUsersQuery);
String ldapSearchBase = propFile.getProperty(Constants.eDir_SearchBase);
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<SearchResult> resultsApp = ctx.search(ldapSearchBase, searchFilter, searchControls);
int i = 0;
while (resultsApp.hasMoreElements()) {
SearchResult result = (SearchResult) resultsApp.next();
String DN = "";
DN = result.getNameInNamespace();
if (!DN.isEmpty()) {
eDir_AllUsersDNList.add(i, DN);
i++;
}
resultsApp.nextElement();
}
System.out.println("eDir_AllUsersDNList : "+eDir_AllUsersDNList.size());
Please help me to find out the issue.
I am using Java 8.
while (resultsApp.hasMoreElements()) {
SearchResult result = (SearchResult) resultsApp.next();
String DN = "";
DN = result.getNameInNamespace();
if (!DN.isEmpty()) {
eDir_AllUsersDNList.add(i, DN);
i++;
}
resultsApp.nextElement();
}
Remove the final nextElement() call. It is doing nothing useful, and it is skipping all the even-numbered elements. Note that 8531 is half of 17062.
NB the cast is redundant, and the DN can't be empty, and providing an initializer for it when you assign it on the very next line is pointless.
I want to get the list of all sAMAccountName from ldap, Below is the method which gives me the Ldap attributes of a user by using samAccountName
public static void searchUserFromLdap(String samAccountName) throws Exception{
SearchResult searchResult = ldapConnection.search("CN=XX,DC=XX,DC=XX", SearchScope.SUB, "(sAMAccountName=" + samAccountName +")");
if(searchResult.getSearchEntries().size()<=0){
System.out.println("No such user found in LDAP");
return;
}
System.out.println("Start :- LDAP attributes for given user\n");
for(SearchResultEntry searchResultEntry : searchResult.getSearchEntries()){
System.out.println(searchResultEntry.toLDIFString());
}
System.out.println("\nEnd :- LDAP attributes for given user");
}
This method accept the samAccountName and returns the ldap attributes for user
I want to get the list of all samAccountName, I have searched for this but i didn't get anything relevent, Can anyone please tell how can i get the list of sAMAccountName.
I'm not sure what ldapConnection is. Is it from unboundid?
Either way from the look of the method the third parameter is your LDAP search filter. You can simply change this filter to be the following:
(objectClass=user)
So the method call would be:
SearchResult searchResult = ldapConnection.search(
"CN=XX,DC=XX,DC=XX",
SearchScope.SUB,
"(objectClass=user)");
The SearchResult will then contain all users found under CN=XX,DC=XX,DC=XX.
If it is from unboundid, then you can add in a 4th parameter to define that you only want the sAMAccountName ldap attribute to be returned for each result. So this would be:
SearchResult searchResult = ldapConnection.search(
"CN=XX,DC=XX,DC=XX",
SearchScope.SUB,
"(objectClass=user)",
"sAMAccountName");
For more details on LDAP search filters see the following resource:
http://docs.oracle.com/cd/E19528-01/819-0997/gdxpo/index.html
I am not sure about the above post as i haven't tried it, But after reading the oracle documentation http://docs.oracle.com/cd/E19957-01/816-6402-10/search.htm I modified my search query and it worked, Here is what i have done
public static void getListOfAllSamAccountName() throws Exception {
List<String> samAccountNameList = null;
SearchResult searchResult = ldapConnection.search(
"CN=XX,DC=XX,DC=xx", SearchScope.SUB,
"(sAMAccountName=*)");
if (searchResult.getSearchEntries().size() <= 0) {
System.out.println("No such user found in LDAP");
return;
}
samAccountNameList = new ArrayList<String>();
System.out.println("Start :- LDAP attributes for given user\n");
for (SearchResultEntry searchResultEntry : searchResult
.getSearchEntries()) {
Attribute attribute = searchResultEntry
.getAttribute("sAMAccountName");
String samAccountName = attribute.getValue();
samAccountNameList.add(samAccountName);
}
if (samAccountNameList != null) {
System.out
.println("*******************************List of Same account Name******************************");
for (String samAccountName : samAccountNameList) {
System.out.println(samAccountName);
}
}
System.out.println("\nEnd :- LDAP attributes for given user");
}
im trying to get the User Permissions (read, write, browse,...) for LDAP objects using a java application with shiro. I dont have much experience with LDAP. I set up a server with Apache Directory Studio for testing purpose. Then i created a domain (dc=testdomain) and added a subentry with the "accessControlSubentry" objectclass and added the "prescriptiveACI" attribute. Everthing works the way it should if i browse the server with Apache DS and i can connect to the server in my java app.
In order to get the permissions i subclassed the ActiveDirectoryRealm from shiro. But i cant manage to make the query get the subentrys.
private Set<String> getPermissionsForUser(String username, LdapContext ldapContext) throws NamingException{
Set<String> permissions;
permissions = new LinkedHashSet<String>();
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchCtls.setReturningAttributes(new String[]{"prescriptiveACI"});
String searchFilter = "(objectClass=subentry)";
String searchBase = "dc=testdomain";
NamingEnumeration answer = ldapContext.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
if (log.isDebugEnabled()) {
log.debug("Retrieving permissions for user [" + sr.getName() + "]");
}
Attributes attrs = sr.getAttributes();
if (attrs != null) {
NamingEnumeration ae = attrs.getAll();
while (ae.hasMore()) {
Attribute attr = (Attribute) ae.next();
if (attr.getID().equals("prescriptiveACI")) {
if (log.isDebugEnabled()) {
log.debug("Permissions found");
}
}
}
}
}
return permissions;
}
When I change the searchFilter to "(objectClass=*)" i get all the OrganisationUnits in the domain. But i just cant seem to find the subentry objects that i need for the prescriptiveACI attribute.
Here is the content of my Shiro.ini file
activeDirectoryRealm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealmPermissions
activeDirectoryRealm.systemUsername = uid=admin,ou=system
activeDirectoryRealm.systemPassword = secret
activeDirectoryRealm.url = ldap://localhost:10389
activeDirectoryRealm.searchBase = ""
How can i make the search query subentries? Or is there a better/alternative way to get the permission from the LDAP server?
So you want to find all instances of accessControlSubentry objects with a prescriptiveACI attribute?
Try this:
(&(objectClass=accessControlSubentry)(prescriptiveACI=*))
I'm currently running into issues when searching for entries where the DN contains a comma:
StringTokenizer st = new StringTokenizer(dn, "=");
Attributes searchAttributes = new BasicAttributes(st.nextToken(), st.nextToken());
Enumeration results = ctx.search(baseDn, searchAttributes);
if (results.hasMoreElements()) {
// ...
}
I tested both dn=first,second as well as dn=first\,second, and although the search runs correctly, I never get any results back. The same baseDn and dn works correctly in Eclipse/Apache Directory Studio LDAP Browser.
depends of libraries, for example by using Novell ldap.jar is constuctor
searchResults = lc.search(searchBase, searchScope, searchFilter, null, false);
//private String searchFilter = "(objectClass=*)";
again depends or libraries, because maybe Directory Studio LDAP Browser has own driver, and some methods are implemented another maybe not, for example with ldap.jar is able to seach in ActiveDirectory
basically all libraries (including Java driver for Windows ActiveDirectory) contains tons of examples packed with library, for most importand of methods which are implemented into driver
EDIT:
hmmm, but there are two relevant
1/ access for context given by admin (between enviroments)
2/ with ActiveDirectory (always) and with (old PC) test enviroment for LDAP I must force for thread(s) some small pause
private void readData() {
searchResults = new LDAPSearchResults();
try {
Thread.sleep(450);
} catch (InterruptedException ex) {
Logger.getLogger(Profylaxia.class.getName()).log(Level.SEVERE, null, ex);
}
try {
searchResults = lc.search(searchBase, searchScope, searchFilter, null, false);
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(Profylaxia.class.getName()).log(Level.SEVERE, null, ex);
}
int noResult = searchResults.getCount();
System.out.println(" noResult : " + noResult);
// thenafter I can able to start Iterations....
The quoting rules for ldap queries can be found at http://www.rlmueller.net/CharactersEscaped.htm
I'm using the following code snippet to query the cn, should work teh same for the dn:
String searchFilter = "(&(objectClass=user)(cn=" + query + "))";
SearchControls searchControls = new SearchControls();
String[] resultAttributes = {"cn", "distinguishedName", "displayName", "lastLogon", "description"};
searchControls.setReturningAttributes(resultAttributes);
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration ne = getContext().search(root, searchFilter, searchControls);
List<DirectoryUser> result = new ArrayList<DirectoryUser>();
while (ne.hasMoreElements()) {
SearchResult searchResult = (SearchResult)ne.nextElement();
Attributes attrs = searchResult.getAttributes();
...
}