SPNEGO get user details - java

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();

Related

JAVA LDAP : How do I obtain the Dn?

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;
}

Ldap get users in a distribution list

I'm trying to get all the users of a DL using below code.The code is working as expected. However, I'm not able to get AD usernames for some users. Ex. First row of the o/p has username rkama but not the second row. Is this LDAP data issue or is there a different way to get user name/email address in a DL.
O/p
Entry is : CN=Ay\,Ram(rkama),OU=Site-SJN,OU=Accounts_User,DC=corp,DC=XXX,DC=com
Entry is : CN=Wang\,Peter(),OU=Site-SJN,OU=Accounts_User,DC=corp,DC=XXX,DC=com
public ArrayList<String> getAllDLs(String dlname) throws NamingException {
ArrayList<String> dls = new ArrayList<String>();
String attributes[] = { "member", "displayName" };
createDLContext();
SearchControls ctrl = new SearchControls();
ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE);
ctrl.setReturningAttributes(attributes);
String search = "(&(objectClass=group)((sAMAccountName="+dlname+"*)))";
NamingEnumeration enumeration = dlContext.search("", search, ctrl);
while (enumeration.hasMoreElements()) {
SearchResult result = (SearchResult) enumeration.next();
System.out.println("Found match & result is : " + result);
NamingEnumeration<?> n2 = result.getAttributes().get("member").getAll();
while (n2 != null && n2.hasMore()) {
String dlList = (String) n2.next();
System.out.println("Entry is : " + dlList);
}
}
dlContext.close();
return dls;
}
I think you need to escape the \ character. Have a look at http://www.rlmueller.net/CharactersEscaped.htm
The member element only contains a DN for the user, this is not the username or password of the account, but a value that can be put back into the search to get the user information (including cn - the name of the user, and sAMAccountName - the userid of the user).
So you need to feed the dlList value into a second search (cleanly) e.g.
NamingEnumeration searchResult = dlContext.search("", "(dn={1})", new Object[]{ dlList }, ctrl);
Trying to construct the search with a simple string like "(&(objectClass=group)((sAMAccountName="+dlname+"*)))" will yield problems because the elements of the returned string will need to be escaped before putting it into the search (the \ for example).

Java- Retrieving permissions from LDAP for shiro

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=*))

LDAP search in java: DN contains ,

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();
...
}

How to show all objectclasses description of ldap directory using jndi

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 );

Categories

Resources