Wednesday, 3 October 2007

Java: How to tell if an LDAP user is member of a group

Here is a Java class that I use in order to determine if a user of an LDAP server is a member of a group. The class uses the Mozilla LDAP SDK available for download from Mozilla

In many JSF applications this class lies in the heart of my UserInfo managed beans allowing or f orbiting access to various parts of the application.

Things you need to fill before using it are :

  • server name or IP address
  • Server port
  • A user name and a password that will allow your code to execute queries on the LDAP Server
  • The base DN to start the search at

The usual place to find these values is the LDAP server itself. If you server is an Oracle IAS 10.2 infrastructure then check the file $ORACLE_HOME/install/portlist.ini.


package ab.util.ldap;

import java.util.Enumeration;

import netscape.ldap.LDAPAttribute;
import netscape.ldap.LDAPConnection;
import netscape.ldap.LDAPEntry;
import netscape.ldap.LDAPException;
import netscape.ldap.LDAPReferralException;
import netscape.ldap.LDAPSearchResults;

public class MyLDAP 
{
    public static final String ldapHost = "ldap.shelman.int";
    public static final int ldapPort = 3060;
    private static final String authid = "cn=orcladmin";
    private static final String authpw = "my_password";
    private static final String base = "cn=groups,dc=shelman,dc=int";

    /**
     * isGroupMember -- determine if user belongs to an LDAP group
     *
     * #param group name of group to examine
     * #param user name user to search for emembership+-
     */
    public static boolean isGroupMember(String group, String user) 
    {
        String member = "cn=" + user.toLowerCase();
        String filter = "(cn=" + group + ")";
        String[] attrs = { "uniquemember" };
        boolean result = false;

        LDAPConnection ld = new LDAPConnection();
        // System.out.println("Attempting to connect :"  + today.toString());
        try {
            // connect to server and authenticate
            ld.connect(ldapHost, ldapPort, authid, authpw);
            // issue the search request
            LDAPSearchResults res =
                ld.search(base, ld.SCOPE_SUB, filter, attrs, false);
            // loop on results until complete
            while (res.hasMoreElements()) {
                try {
                    LDAPEntry entry = res.next();
                    LDAPAttribute atr = entry.getAttribute(attrs[0]);
                    Enumeration enumVals = atr.getStringValues();

                    while (enumVals != null && enumVals.hasMoreElements()) {
                        String val = (String)enumVals.nextElement();
                        // convert to lower case
                        val = val.toLowerCase();

                        if (val.indexOf(member) >= 0) {
                            result = true;
                            break;
                        }
                    }

                } catch (LDAPReferralException ex) {
                    // ignore referal exceptions
                    continue;
                } catch (LDAPException ex) {
                    System.out.println(ex.toString());
                    continue;
                }
            }
        } catch (Exception ex) {
            System.out.println("Error communicating with LDAP Server " +
                               ldapHost + " Port " + ldapPort);
            System.out.println(ex.toString());
        }

        // finished searching. try to disconnect
        if (ld != null && ld.isConnected()) {
            try {
                ld.disconnect();
            } catch (LDAPException ex) {
                System.out.println(ex.toString());
            }
        }

        // return whatever found
        return result;
    }
}

The package ldapjdk-4.17-38 is included in the distribution of all openSUSE systems. For openSUSE 10.2 the package is available for download from here.

1 comment :

Unknown said...

if you already have a context named ctx then

public boolean isMember(String base, String cn, String uid ) throws NamingException{
Attributes ma = new BasicAttributes (true);
ma.put("objectclass", "groupOfUniqueNames");
ma.put("cn", cn);
ma.put("uniquemember",uid);
NamingEnumeration ne = ctx.search(base, ma );
return ne.hasMore ();
}


public static void main(String[] args) {
try {
Ldap ldap = new Ldap("com.sun.jndi.ldap.LdapCtxFactory","ldap://sellovista:10389" ,"simple", "uid=admin,ou=system", "secret" );
System.out.println(ldap.isMember("ou=roles,ou=groups,o=sars","pmdsadmins", "uid=S1017086,ou=people,o=sars"));
ldap.disconnect();

} catch ( NamingException ne ) {
System.out.print(ne.toString());
}
}