gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 22:32:53 25 4
gpt4 key购买 nike

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

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

在这种情况下,很容易更改或读取为用户存储的信息,但我如何检查他们的密码?通常我会做一个新的连接来检查用户密码。像这样:

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

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

谢谢拉斐尔

最佳答案

这是一种解决方案,可用于使用 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;
}

关于java - 如何使用给定的 LdapContext 在 ldap whith java 中检查用户密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2522770/

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