【发布时间】:2016-09-08 20:41:14
【问题描述】:
又是我。不幸的是,我没有找到我遇到的这个特定问题的答案。让我解释一下我要做什么。
我正在开发一个小型系统来控制我工作和学习的大学的计算机实验室。用户将使用他们的域用户登录系统。集成本身正在运行,我已经能够检索有关用户的一些信息,例如他们所属的组、他们的姓名和其他内容(有关以下代码的更多信息)。但我想做的正是像戴尔的 SonicWall 那样。用户使用他的 AD 帐户访问 SonicWall,他们所属的组允许他们访问某些网站。
我也想通过 AD 组控制访问级别,为此我只需要检索某些组以供系统验证用户应具有的权限。
- labinfo_prof:教授应该加入的组。这将使他们能够访问图书实验室,以便他们可以使用它们。
- labinfo_coord:课程协调员将加入的组。它可以让他们访问图书实验室并控制他们的教授正在使用哪些实验室。
- labinfo_admin:系统管理员将加入的组。这将使他们能够完全访问系统。
- labinfo_est:实习生将加入的组。这将使他们能够访问实验室状态等信息。
这是系统简介。这就是我想要做的:使用 AD 组为用户提供某些权限,但我无法仅检索以 labinfo_ 开头的组。下面是我到目前为止的代码。
我的主要课程,我正在使用的 make 测试。
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 类,其中包含提供用户信息的预制方法。
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 + ")),但我一直收到同样的错误。
【问题讨论】:
-
我在任何地方都没有看到问题。当你尝试你的代码时会发生什么?有什么错误吗?你期望得到什么,你实际得到什么?
-
使用原始代码中显示的 LDAP 查询,我没有收到错误消息,但程序返回我搜索的用户所属的所有组。我正在尝试优化该查询,使其仅显示以“labinfo_”开头的组。查看我原始帖子的最后编辑。我稍微更改了 LDAP 查询,但要优化搜索,但现在我遇到了异常。
标签: java login active-directory active-directory-group