I want to show all objectclasses present in schema of LDAP Directory to help user to input available objectclasses for adding new entry.
DirContext schema = ctx.getSchema("");
Attributes answer = schema.getAttributes("ClassDefinition/person");
but that shows information about person only.
DirContext schema=dcx.getSchema("");
NamingEnumeration bindings = schema.listBindings("ClassDefinition");
while (bindings.hasMore())
{
Binding bd = (Binding)bindings.next();
System.out.println(bd.getName() + ": " + bd.getObject());
}
You can use various other bindings like AttributeDefinition
ClassDefinition
SyntaxDefinition
Schema context may also provide bindings likeMatchingRule
ExtensionDefinition
ControlDefinition
SASLDefinition
You have to query the subschema subentry i.e cn=schema
(the below code has been tested against the Apache Directory Server)
DirContext ctx = new InitialLdapContext( env, null );
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope( SearchControls.OBJECT_SCOPE );
searchControls.setReturningAttributes( new String[]
{ "objectClasses" } );
NamingEnumeration<SearchResult> results = ctx.search( "cn=schema", "(ObjectClass=*)", searchControls );
SearchResult result = results.next();
Attributes entry = result.getAttributes();
Attribute objectClasses = entry.get( "objectClasses" );
System.out.println( objectClasses );
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.
I have setup the spnego library in tomcat using the JNDIRealm.
Followed following guide : https://dzone.com/articles/do-not-publish-configuring-tomcat-single-sign-on-w
I would like to know I have could get the users group from LDAP in another java class I am using to create a user in my database. I would like to get all user details like email, phone etc.. as well as all the groups the user is part of.
See this list to get all the attributes you can retrieve from LDAP.
For example, let's say you want the Name, Group, Job Title, Phone Number and E-mail of your users. (For consistancy with your question, I'll use the same "dummy value" as your link).
The first step is to connect to LDAP in your Java class, for that I rather use a separate function :
public static Hashtable<String, String> getContextEnv() {
Hashtable<String, String> contextEnv = new Hashtable<String, String>();
contextEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
contextEnv.put(Context.PROVIDER_URL, "ldap://dc.mydomain.com:3268");
contextEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
contextEnv.put(Context.SECURITY_PRINCIPAL, "CN=TECHNICAL_USER,DC=mydomain,DC=com");
contextEnv.put(Context.SECURITY_CREDENTIALS, "TECHNICAL_USER_PASSWORD");
contextEnv.put("java.naming.referral", "follow");
contextEnv.put("java.naming.ldap.derefAliases", "never");
contextEnv.put("com.sun.jndi.ldap.connect.pool", "true");
contextEnv.put("com.sun.jndi.ldap.connect.timeout", "60000");
return contextEnv;
}
Where TECHNICAL_USER is the one you use to create your keytab with the ktpass command.
Next step is to call that function, and create a SearchControls object. This is where you will put the attribute you want to get (see the link above for all the possibilities) and some paramaters (timeout for example) :
Hashtable<String, String> contextEnv = getContextEnv();
DirContext ctx = new InitialDirContext(contextEnv);
// UserID - Last Name - First Name - Group - Job Title - Phone Number - Email address
String[] attrIDs = { "sAMAccountName", "sn", "givenName", "memberOf", "title", "telephoneNumber", "mail"};
SearchControls searchControls = new SearchControls();
searchControls.setReturningAttributes(attrIDs);
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setTimeLimit(6000);
Final step, you get the info of your current user where currentUser is the UserID your corporation use to identify the employees :
NamingEnumeration<SearchResult> searchResults = ctx.search("DC=mydomain,DC=com", "(sAMAccountName=" + currentUser + ")", searchControls);
if (searchResults.hasMore()) {
SearchResult currentSearchResult = searchResults.next();
Attributes searchResultAttributes = currentSearchResult.getAttributes();
String userID = searchResultAttributes.get("sAMAccountName");
String lastName = searchResultAttributes.get("sn");
String firstName = searchResultAttributes.get("givenName");
String group = searchResultAttributes.get("memberOf");
String jobTitle = searchResultAttributes.get("title");
String phoneNumber = searchResultAttributes.get("telephoneNumber");
String email = searchResultAttributes.get("mail");
searchResults.close();
}
ctx.close();
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;
}
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();
...
}