使用 Java 从 AD 获取特定组

Getting Specific Group from AD using Java

又是我。不幸的是,我没有找到我遇到的这个特定问题的答案。让我解释一下我要做什么。

我正在开发一个小型系统来控制我工作和学习的大学的计算机实验室。用户将使用他们的域用户登录系统。集成本身正在运行,我已经能够检索有关用户的一些信息,例如他们所属的组、他们的姓名和其他内容(有关下面代码的更多信息)。但我想做的正是戴尔的 SonicWall 所做的事情。用户使用他的 AD 帐户访问 SonicWall,他们所属的组允许他们访问某些网站。

我也想通过AD组来控制访问级别,为此我只需要为系统检索某些组来验证用户应该拥有的权限。

这是系统简介。这就是我想要做的:使用 AD 组为用户提供某些权限,但我无法仅检索以 labinfo_ 开头的组。下面是我目前的代码。

我的主要 class,我正在使用的那个进行测试。

import java.io.*;
import java.util.*;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchResult;

public class ActiveDirectoryTest {

    public static void main(String[] args) throws NamingException, IOException {
        try {
            String domain = "umc.br";
            String ch = "username";
            String user, pwd, search;
            Console console = System.console();
            Scanner scan = new Scanner(System.in);

            System.out.print("Usuário: ");
            user = scan.next();
            pwd = String.valueOf(console.readPassword("Senha: "));
            System.out.print("Termo de busca: ");
            search = scan.next();

            ActiveDirectory activeDirectory = new ActiveDirectory(user, pwd, domain);
            NamingEnumeration<SearchResult> result = activeDirectory.searchUser(search, ch, null);

            if (result.hasMore()) {
                SearchResult rs = (SearchResult) result.next();
                Attributes attrs = rs.getAttributes();
                String cn = attrs.get("cn").toString();
                System.out.println("Nome completo: " + cn.substring(cn.indexOf(":") + 1));
                String samaccountname = attrs.get("samaccountname").toString();
                System.out.println("Usuário: " + samaccountname.substring(samaccountname.indexOf(":") + 1));
                String groups = attrs.get("memberOf").toString();               
                System.out.println("Grupo: " + groups);
                if (attrs.get("mail") == null) {
                    System.out.println("Email: não cadastrado");
                } else {
                    String mail = attrs.get("mail").toString();
                    System.out.println("Email: " + mail.substring(mail.indexOf(":") + 1));
                }
            } else {
                System.out.println("Resultado não encontrado!");
            }
            activeDirectory.closeLdapConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我在 Internet 上找到的 ActiveDirectory class,使用预制方法可以提供有关用户的信息。

import java.util.Properties;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

public class ActiveDirectory {

    private static final Logger LOG = Logger.getLogger(ActiveDirectory.class.getName());
    private Properties properties;
    private DirContext dirContext;
    private SearchControls searchCtls;
    private String[] returnAttributes = {"sAMAccountName", "givenName", "cn", "mail", "memberOf"};
    private String domainBase;
    private String baseFilter = "(&((&(objectCategory=Person)(objectClass=User)))";

    public ActiveDirectory(String username, String password, String domainController) {
        properties = new Properties();

        properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        properties.put(Context.PROVIDER_URL, "LDAP://" + domainController);
        properties.put(Context.SECURITY_PRINCIPAL, username + "@" + domainController);
        properties.put(Context.SECURITY_CREDENTIALS, password);

        try {
            dirContext = new InitialDirContext(properties);
        } catch (NamingException e) {
            LOG.severe(e.getMessage());
        }

        domainBase = getDomainBase(domainController);

        searchCtls = new SearchControls();
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        searchCtls.setReturningAttributes(returnAttributes);
    }

    public NamingEnumeration<SearchResult> searchUser(String searchValue, String searchBy, String searchBase) throws NamingException {
        String filter = getFilter(searchValue, searchBy);
        String base = (null == searchBase) ? domainBase : getDomainBase(searchBase);

        return this.dirContext.search(base, filter, this.searchCtls);
    }

    public void closeLdapConnection() {
        try {
            if (dirContext != null) {
                dirContext.close();
            }
        } catch (NamingException e) {
            LOG.severe(e.getMessage());
        }
    }

    private String getFilter(String searchValue, String searchBy) {
        String filter = this.baseFilter;
        if (searchBy.equals("email")) {
            filter += "(mail=" + searchValue + "))";
        } else if (searchBy.equals("username")) {
            filter += "(samaccountname=" + searchValue + "))";
        }
        return filter;
    }

    private static String getDomainBase(String base) {
        char[] namePair = base.toUpperCase().toCharArray();
        String dn = "DC=";
        for (int i = 0; i < namePair.length; i++) {
            if (namePair[i] == '.') {
                dn += ",DC=" + namePair[++i];
            } else {
                dn += namePair[i];
            }
        }
        return dn;
    }
}

编辑:我更改了 LDAP 查询以查看是否可行。嗯,异常变了,哈哈。现在它给了我 javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name 'DC=UMC,DC=BR'.

当前的 LDAP 查询是 (&((&(objectClass=group)(name=labinfo_*))&(objectCategory=Person)(objectClass=User))(samaccountname=" + searchValue + "))

EDIT2:我现在将 LDAP 查询更改为 (&(&(objectCategory=person)(objectClass=user))(&(objectCategory=group)(sAMAccountName=labinfo_*))(sAMAccountName=" + searchValue + ")),但我一直收到同样的错误。

我设法 return 通过使用查询 (&(objectClass=user)(memberOf=CN=" + group + ",OU=FIFTH_OU,OU=FOURTH_OU,OU=THIRD_OU,OU=SECOND,OU=FIRST_OU,DC=umc,DC=br)(sAMAccountName=" + searchValue + "))" 只有我想要的组。我必须为该组提供整个路径,包括所有 OU 和 DC。困扰了我很久,终于成功了。