LDAP搜索中的NPE

时间:2014-01-11 12:37:38

标签: java ldap openldap

我使用以下配置安装并配置了OpenLDAP服务器:

# Entry 1: dc=unixmen,dc=com
dn: dc=unixmen,dc=com
dc: unixmen
o: unixmen
objectclass: top
objectclass: dcObject
objectclass: organization

# Entry 2: cn=ServerAdmins,dc=unixmen,dc=com
dn: cn=ServerAdmins,dc=unixmen,dc=com
cn: ServerAdmins
gidnumber: 501
objectclass: posixGroup
objectclass: top

# Entry 3: cn=rcbandit,cn=ServerAdmins,dc=unixmen,dc=com
dn: cn=rcbandit,cn=ServerAdmins,dc=unixmen,dc=com
cn: rcbandit
gidnumber: 501
givenname: rcbandit
homedirectory: /home/users/rcbandit
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: top
sn: rcbandit
uid: rcbandit
uidnumber: 1000
userpassword: {MD5}2FeO34RYzgb7xbt2pYxcpA==

我测试了这个简单的Java LDAP客户端,以便通过发送用户名和密码来验证用户身份:

public class MainApp
{

    public static String ldapHostUrl = null;
    public static String ldapBindDN = null;
    public static String ldapBindPwd = null;

    public MainApp()
    {

    }

    /**
     * Generic method to obtain a reference to a DirContext
     */
    public DirContext getDirContext() throws Exception
    {
        Hashtable<String, String> env = new Hashtable<String, String>(11);
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, getLdapHostUrl());
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, ldapBindDN);
        env.put(Context.SECURITY_CREDENTIALS, ldapBindPwd);
        DirContext ctx = new InitialDirContext(env);
        return ctx;
    }

    /**
     * Generic method to obtain a reference to the user ENV
     */
    public static Hashtable<String, String> getUserEnv()
    {
        Hashtable<String, String> env = new Hashtable<String, String>(11);
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, getLdapHostUrl());
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        return env;
    }

    /**
     *
     * @param attributeName String - Standard ID (userID)
     * @throws Exception -
     */
    public void doFindEntries(String attributeValue, String attributeName, String searchBase) throws Exception
    {
        DirContext xctx = getDirContext();
        SearchControls searchCons = getSimpleSearchControls();
        String searchFilter = "(" + attributeName + "=" + attributeValue + ")";
        // Search for objects with those matching attributes
        NamingEnumeration<?> answer = xctx.search(searchBase, searchFilter, searchCons);
        //formatResults(answer);
        xctx.close();
    }

    public String getDN(String name, String ldapUserIDAttribute, String ldapBaseForusers) throws NamingException, Exception
    {
        String dn = null;
        String searchFilter = "(" + ldapUserIDAttribute + "=" + name + ")";
        SearchControls searchCons = getSimpleSearchControls();
        searchCons.setReturningAttributes(new String[0]);
        NamingEnumeration<?> results = getDirContext().search(ldapBaseForusers, searchFilter, searchCons);
        int thisCount = 0;
        if (results != null && results.hasMore())
        {
            if (thisCount > 0)
            {
                throw new NamingException("More than one Result was found!");
            }
            SearchResult si = (SearchResult) results.next();
            dn = si.getNameInNamespace();
            thisCount++;
        }
        return dn;
    }

    /**
     * I am just lazy and hate to type.
     *
     * @return
     */
    public static SearchControls getSimpleSearchControls()
    {
        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        searchControls.setTimeLimit(30000);
        return searchControls;
    }

    public static void testUserCredentials(String userFdn, String userPassword) throws NamingException
    {
        Hashtable<String, String> userEnv = getUserEnv();
        userEnv.put(Context.SECURITY_PRINCIPAL, userFdn);
        userEnv.put(Context.SECURITY_CREDENTIALS, userPassword);
        DirContext userCtx = new InitialDirContext(userEnv);
    }

    /**
     * Reads from console and works in Eclipse
     *
     * @param prompt
     * @return
     */
    private static String readLine(String prompt)
    {
        String line = null;
        Console c = System.console();
        if (c != null)
        {
            line = c.readLine(prompt);
        }
        else
        {
            System.out.print(prompt);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            try
            {
                line = bufferedReader.readLine();
            }
            catch (IOException e)
            {
                // Ignore
            }
        }
        return line;
    }

    static String getLdapHostUrl()
    {
        return ldapHostUrl;
    }

    static void setLdapHostUrl(String ldapHostUrl)
    {
        ldapHostUrl = ldapHostUrl;
    }

    static String getLdapBindDN()
    {
        return ldapBindDN;
    }

    static void setLdapBindDN(String ldapBindDN)
    {
        ldapBindDN = ldapBindDN;
    }

    static String getLdapBindPwd()
    {
        return ldapBindPwd;
    }

    static void setLdapBindPwd(String ldapBindPwd)
    {
        ldapBindPwd = ldapBindPwd;
    }

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        System.out.println("Performing LDAP Operations with the Following:");

        MainApp ss = new MainApp();
        MainApp.setLdapHostUrl("ldap://192.168.1.177:389");
        MainApp.setLdapBindDN("cn=rcbandit,cn=ServerAdmins,dc=unixmen,dc=com");
        MainApp.setLdapBindPwd("qwerty");
        String ldapBaseForusers = "cn";
        String ldapUserIDAttribute = "simple";

        while (true)
        {
            String userFindValue = null;
            String userFdn = null;
            String userPassword = null;
            // /Find a user
            userFindValue = "rcbandit";
            userPassword = "qwerty";
            System.out.println("Return All Attributes for ALL users by: " + ldapUserIDAttribute + " = " + userFindValue);

            try
            {
                ss.doFindEntries(userFindValue, ldapUserIDAttribute, ldapBaseForusers);
            }
            catch (javax.naming.PartialResultException e)
            {
                System.out.println("Find user DN by Name: Returned a PartialResultException\n" + e.getMessage());
            }
            catch (Exception e)
            {
                System.out.println("Find user DN by Name: FAILED\n" + e.getMessage());
            }

            System.out.println();
            System.out.println("Find user DN by: " + ldapUserIDAttribute + " = " + userFindValue);
            System.out.println("====================================================");
            try
            {
                userFdn = ss.getDN(userFindValue, ldapUserIDAttribute, ldapBaseForusers);
                System.out.println("DN: " + userFdn);
            }
            catch (NamingException e)
            {
                if (e instanceof javax.naming.PartialResultException)
                {
                    // ignore
                }
                else
                {
                    System.out.println("Find user DN by Name: Returned a PartialResultException\n" + e.getMessage());
                }
            }
            catch (Exception e)
            {
                System.out.println("Find user DN by Name: FAILED\n" + e.getMessage());
            }
            System.out.println();
            System.out.println("Test User's Credentials: ");
            System.out.println("====================================================");
            try
            {
                testUserCredentials(userFdn, userPassword);
                System.out.println("Test User's Credentials: SUCCESS!");
            }
            catch (NamingException e)
            {
                System.err.println("Test User's Credentials: FAILED\n" + e.getMessage());
            }
        }// end while
    }
}

运行代码时,我得到了这个结果:

Find user DN by: simple = rcbandit
====================================================
Find user DN by Name: FAILED
null

Test User's Credentials: 
====================================================
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.javafx.main.Main.launchApp(Main.java:714)
    at com.javafx.main.Main.main(Main.java:871)
Caused by: java.lang.NullPointerException
    at java.util.Hashtable.put(Hashtable.java:514)
    at dx57.ldapclient.MainApp.getUserEnv(MainApp.java:52)
    at dx57.ldapclient.MainApp.testUserCredentials(MainApp.java:109)
    at dx57.ldapclient.MainApp.main(MainApp.java:240)
    ... 6 more

你能帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

我会说&#39; getLdapHostUrl()&#39;返回null,但我也会说你真的被指控能够调试你自己的NPE,尤其是像这样的微不足道的NPE。至少我期待它。