gpt4 book ai didi

跨受信任域的 Java AD 身份验证

转载 作者:行者123 更新时间:2023-12-02 01:05:51 26 4
gpt4 key购买 nike

我正在尝试在 Java 中实现 Active Directory 身份验证,该身份验证将在 Linux 计算机上运行。我们的 AD 设置将由多台服务器组成,这些服务器彼此共享信任关系,因此对于我们的测试环境,我们有两个域 Controller :

test1.ad1.foo.com谁信任test2.ad2.bar.com

使用下面的代码我可以成功验证 test1 中的用户但不在test2上:

public class ADDetailsProvider implements ResultSetProvider {
private String domain;
private String user;
private String password;

public ADDetailsProvider(String user, String password) {
//extract domain name
if (user.contains("\\")) {
this.user = user.substring((user.lastIndexOf("\\") + 1), user.length());
this.domain = user.substring(0, user.lastIndexOf("\\"));
} else {
this.user = user;
this.domain = "";
}

this.password = password;
}

/* Test from the command line */
public static void main (String[] argv) throws SQLException {
ResultSetProvider res = processADLogin(argv[0], argv[1]);
ResultSet results = null;
res.assignRowValues(results, 0);
System.out.println(argv[0] + " " + argv[1]);
}


public boolean assignRowValues(ResultSet results, int currentRow)
throws SQLException
{
// Only want a single row
if (currentRow >= 1) return false;

try {
ADAuthenticator adAuth = new ADAuthenticator();
LdapContext ldapCtx = adAuth.authenticate(this.domain, this.user, this.password);
NamingEnumeration userDetails = adAuth.getUserDetails(ldapCtx, this.user);

// Fill the result set (throws SQLException).
while (userDetails.hasMoreElements()) {
Attribute attr = (Attribute)userDetails.next();
results.updateString(attr.getID(), attr.get().toString());
}

results.updateInt("authenticated", 1);
return true;

} catch (FileNotFoundException fnf) {
Logger.getAnonymousLogger().log(Level.WARNING,
"Caught File Not Found Exception trying to read cris_authentication.properties");

results.updateInt("authenticated", 0);
return false;

} catch (IOException ioe) {
Logger.getAnonymousLogger().log(Level.WARNING,
"Caught IO Excpetion processing login");

results.updateInt("authenticated", 0);
return false;

} catch (AuthenticationException aex) {
Logger.getAnonymousLogger().log(Level.WARNING,
"Caught Authentication Exception attempting to bind to LDAP for [{0}]",
this.user);

results.updateInt("authenticated", 0);
return true;

} catch (NamingException ne) {
Logger.getAnonymousLogger().log(Level.WARNING,
"Caught Naming Exception performing user search or LDAP bind for [{0}]",
this.user);
results.updateInt("authenticated", 0);
return true;
}
}

public void close() {
// nothing needed here
}

/**
* This method is called via a Postgres function binding to access the
* functionality provided by this class.
*/
public static ResultSetProvider processADLogin(String user, String password) {
return new ADDetailsProvider(user, password);
}
}

public class ADAuthenticator {

public ADAuthenticator()
throws FileNotFoundException, IOException {
Properties props = new Properties();
InputStream inStream = this.getClass().getClassLoader().
getResourceAsStream("com/bar/foo/ad/authentication.properties");

props.load(inStream);
this.domain = props.getProperty("ldap.domain");
inStream.close();
}

public LdapContext authenticate(String domain, String user, String pass)
throws AuthenticationException, NamingException, IOException {
Hashtable env = new Hashtable();
this.domain = domain;

env.put(Context.INITIAL_CONTEXT_FACTORY, com.sun.jndi.ldap.LdapCtxFactory);
env.put(Context.PROVIDER_URL, "ldap://" + test1.ad1.foo.com + ":" + 3268);
env.put(Context.SECURITY_AUTHENTICATION, simple);
env.put(Context.REFERRAL, follow);

env.put(Context.SECURITY_PRINCIPAL, (domain + "\\" + user));
env.put(Context.SECURITY_CREDENTIALS, pass);

// Bind using specified username and password
LdapContext ldapCtx = new InitialLdapContext(env, null);
return ldapCtx;
}

public NamingEnumeration getUserDetails(LdapContext ldapCtx, String user)
throws NamingException {
// List of attributes to return from LDAP query
String returnAttributes[] = {"ou", "sAMAccountName", "givenName", "sn", "memberOf"};

//Create the search controls
SearchControls searchCtls = new SearchControls();
searchCtls.setReturningAttributes(returnAttributes);

//Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

// Specify the user to search against
String searchFilter = "(&(objectClass=*)(sAMAccountName=" + user + "))";

//Perform the search
NamingEnumeration answer = ldapCtx.search("dc=dev4,dc=dbt,dc=ukhealth,dc=local", searchFilter, searchCtls);

// Only care about the first tuple
Attributes userAttributes = ((SearchResult)answer.next()).getAttributes();
if (userAttributes.size() <= 0) throw new NamingException();

return (NamingEnumeration) userAttributes.getAll();
}

根据我对信任关系的理解,如果trust1收到 trust2 中的用户的登录尝试,那么它应该将登录尝试转发给它,并根据用户的域名来解决这个问题。

这是正确的还是我遗漏了一些东西,或者使用上面的方法不可能做到这一点?

--编辑--
LDAP 绑定(bind)的堆栈跟踪是 {java.naming.provider.url=ldap://test1.ad1.foo.com:3268, java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory, java.naming.security.authentication=simple, java.naming.referral=follow}
30-Oct-2012 13:16:02<br/>
ADDetailsProvider assignRowValues
WARNING: Caught Authentication Exception attempting to bind to LDAP for [trusttest]
Auth error is [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db0]

最佳答案

据我所知,您应该将 Context.REFERRAL 设置为 true。
这是你代码中的意思吗?
另外,当我切换到 GSSAPI/Kerberos 时,
我定义了 kerberos 领域之间的信任关系,它对我有用。

关于跨受信任域的 Java AD 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13124591/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com