raf*_*ael 18 java authentication web-applications ldap
我有一个Web应用程序,用户必须登录.密码存储在LDAP服务器中.有关LDAP服务器的所有信息都作为外部jndi资源存储在应用程序服务器(glassfish)中.所以我的应用程序对LDAP服务器一无所知,只得到像这样的LdapContext:
@Resource(name = "ldap/users")
private LdapContext ctx;
Run Code Online (Sandbox Code Playgroud)
使用此上下文,可以轻松更改或读取为用户存储的信息,但如何检查其密码?通常我会做一个新的连接来检查用户密码.像这样:
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);
Run Code Online (Sandbox Code Playgroud)
但由于我不知道这个参数我不能这样做.那么如何使用我的LdapContext检查用户的密码是否正确?密码以加密方式存储(ssha),所以我不能只比较属性.
谢谢拉斐尔
Nik*_*pov 25
这是一种解决方案,可用于使用除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;
}
Run Code Online (Sandbox Code Playgroud)
小智 11
您应该能够从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);
Run Code Online (Sandbox Code Playgroud)