如何在给定LdapContext的ldap whith java中检查用户密码?

raf*_*ael 18 java authentication web-applications ldap

我有一个Web应用程序,用户必须登录.密码存储在LDAP服务器中.有关LDAP服务器的所有信息都作为外部jndi资源存储在应用程序服务器(glassfish)中.所以我的应用程序对LDAP服务器一无所知,只得到像这样的LdapContext:

@Resource(name = "ldap/users")
private LdapContext ctx;
Run Code Online (Sandbox Code Playgroud)

使用此上下文,可以轻松更改或读取为用户存储的信息,但如何检查其密码?通常我会做一个新的连接来检查用户密码.像这样:

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

DirContext ctx = new InitialDirContext(env);
Run Code Online (Sandbox Code Playgroud)

但由于我不知道这个参数我不能这样做.那么如何使用我的LdapContext检查用户的密码是否正确?密码以加密方式存储(ssha),所以我不能只比较属性.

谢谢拉斐尔

Nik*_*pov 25

这是一种解决方案,可用于使用除DN之外的其他内容对用户进行身份验证,例如使用uidsAMAccountName.

要做的步骤是:

  1. 连接到LDAP服务器
  2. 与我们了解DN和凭据的服务用户进行身份验证
  3. 搜索要进行身份验证的用户,使用某个属性搜索他(例如sAMAccountName)
  4. 获取我们找到的用户的DN
  5. 使用找到的DN和密码打开与LDAP服务器的另一个连接
  6. 如果找到用户并且身份验证有效,那么您没问题

代码示例:

public static boolean performAuthentication() {

    // service user
    String serviceUserDN = "cn=Mister Service,ou=Users,dc=example,dc=com";
    String serviceUserPassword = "abc123#!$";

    // user to authenticate
    String identifyingAttribute = "uid";
    String identifier = "maxdev";
    String password = "jkl987.,-";
    String base = "ou=Users,dc=example,dc=com";

    // LDAP connection info
    String ldap = "localhost";
    int port = 10389;
    String ldapUrl = "ldap://" + ldap + ":" + port;

    // first create the service context
    DirContext serviceCtx = null;
    try {
        // use the service user to authenticate
        Properties serviceEnv = new Properties();
        serviceEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        serviceEnv.put(Context.PROVIDER_URL, ldapUrl);
        serviceEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        serviceEnv.put(Context.SECURITY_PRINCIPAL, serviceUserDN);
        serviceEnv.put(Context.SECURITY_CREDENTIALS, serviceUserPassword);
        serviceCtx = new InitialDirContext(serviceEnv);

        // we don't need all attributes, just let it get the identifying one
        String[] attributeFilter = { identifyingAttribute };
        SearchControls sc = new SearchControls();
        sc.setReturningAttributes(attributeFilter);
        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);

        // use a search filter to find only the user we want to authenticate
        String searchFilter = "(" + identifyingAttribute + "=" + identifier + ")";
        NamingEnumeration<SearchResult> results = serviceCtx.search(base, searchFilter, sc);

        if (results.hasMore()) {
            // get the users DN (distinguishedName) from the result
            SearchResult result = results.next();
            String distinguishedName = result.getNameInNamespace();

            // attempt another authentication, now with the user
            Properties authEnv = new Properties();
            authEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            authEnv.put(Context.PROVIDER_URL, ldapUrl);
            authEnv.put(Context.SECURITY_PRINCIPAL, distinguishedName);
            authEnv.put(Context.SECURITY_CREDENTIALS, password);
            new InitialDirContext(authEnv);

            System.out.println("Authentication successful");
            return true;
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (serviceCtx != null) {
            try {
                serviceCtx.close();
            } catch (NamingException e) {
                e.printStackTrace();
            }
        }
    }
    System.err.println("Authentication failed");
    return false;
}
Run Code Online (Sandbox Code Playgroud)


小智 11

您应该能够从ldap上下文获取环境,克隆它,然后为要检查的用户放置主体和凭据:

@Resource(name = "ldap/users")
private LdapContext ldapContext;

Hashtable environment = ldapContext.getEnvironment().clone();
environment.put(Context.SECURITY_PRINCIPAL, userDN);
environment.put(Context.SECURITY_CREDENTIALS, userPassword);

DirContext dirContext = new InitialDirContext(environment);
Run Code Online (Sandbox Code Playgroud)