[英]How to check user password in ldap whith java with given LdapContext?
我有一個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之外的其他內容對用戶進行身份驗證,例如使用uid
或sAMAccountName
。
要做的步驟是:
sAMAccountName
) 代碼示例:
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;
}
您應該能夠從ldap上下文獲取環境,克隆它,然后為要檢查的用戶放置主體和憑據:
@Resource(name = "ldap/users")
private LdapContext ldapContext;
Hashtable environment = ldapContext.getEnvironment().clone();
environment.put(Context.SECURITY_PRINCIPAL, userDN);
environment.put(Context.SECURITY_CREDENTIALS, userPassword);
DirContext dirContext = new InitialDirContext(environment);
我在我的申請中做了同樣的事情。 以下是可能對您有用的內容。
package com.agileinfotech.bsviewer.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
public class Login extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
public Login() {
super();
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final String SUCCESS = "loin.jsp";
final String FAILURE = "Failure.html";
String strUrl = "login.html";
String username = request.getParameter("username");
String password = request.getParameter("password");
Hashtable env = new Hashtable(11);
boolean b = false;
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid="+ username +",ou=system");
env.put(Context.SECURITY_CREDENTIALS, password);
try {
// Create initial context
DirContext ctx = new InitialDirContext(env);
// Close the context when we're done
b = true;
ctx.close();
} catch (NamingException e) {
b = false;
}finally{
if(b){
System.out.print("Success");
strUrl = SUCCESS;
}else{
System.out.print("Failure");
strUrl = FAILURE;
}
}
RequestDispatcher rd = request.getRequestDispatcher(strUrl);
rd.forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request,response);
}
}
在實際應用程序LDAP服務器中,密碼以哈希碼形式存儲,每當任何訪問管理器從用戶獲取密碼時,該純文本密碼將再次使用相同的密鑰進行哈希處理並檢查存儲在LDAP中的密碼。 因此,您無法從LDAP服務器獲取普通密碼。 因此,如果你知道密鑰,那么你才能解密它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.