使用Java从{AD获取特定组

时间:2016-09-08 20:41:14

标签: java login active-directory active-directory-group

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

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

我也希望通过AD组控制访问级别,为此我需要仅检索系统的某些组以验证用户应具有的权限。

  • labinfo_prof:教授应该参加的小组。它可以让他们访问图书实验室,以便他们可以使用它们。
  • labinfo_coord:课程协调员将参与的小组。它可以让他们访问图书实验室并控制他们的教授正在使用哪些实验室。
  • labinfo_admin:系统管理员将成为其中一员的组。它将为他们提供对系统的完全访问权限。
  • labinfo_est:实习生所属的团体。它可以让他们访问实验室状态等信息。

这是关于系统的简要说明。这就是我尝试做的事情:使用AD群组为用户提供某些权限,但我无法只检索以labinfo_开头的群组。下面是我到目前为止的代码。

我的主要课程,我正在使用make test。

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

我在互联网上找到的一个ActiveDirectory类,使用预先制作的方法向我提供有关用户的信息。

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 + ")),但我一直收到同样的错误。

1 个答案:

答案 0 :(得分:0)

我设法通过查询(&(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。它让我困扰了很长时间,但它终于奏效了。