mirror of
https://github.com/sismics/docs.git
synced 2025-12-13 01:36:18 +00:00
LDAP support, courtesy of an anonymous donator
This commit is contained in:
@@ -131,7 +131,12 @@
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Only there to read old index and rebuild them -->
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
|
||||
@@ -44,5 +44,18 @@ public enum ConfigType {
|
||||
INBOX_PASSWORD,
|
||||
INBOX_TAG,
|
||||
INBOX_AUTOMATIC_TAGS,
|
||||
INBOX_DELETE_IMPORTED
|
||||
INBOX_DELETE_IMPORTED,
|
||||
|
||||
/**
|
||||
* LDAP connection.
|
||||
*/
|
||||
LDAP_ENABLED,
|
||||
LDAP_HOST,
|
||||
LDAP_PORT,
|
||||
LDAP_ADMIN_DN,
|
||||
LDAP_ADMIN_PASSWORD,
|
||||
LDAP_BASE_DN,
|
||||
LDAP_FILTER,
|
||||
LDAP_DEFAULT_EMAIL,
|
||||
LDAP_DEFAULT_STORAGE
|
||||
}
|
||||
|
||||
@@ -50,6 +50,19 @@ public class ConfigUtil {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long value of a configuration parameter.
|
||||
*
|
||||
* @param configType Type of the configuration parameter
|
||||
* @return Long value of the configuration parameter
|
||||
* @throws IllegalStateException Configuration parameter undefined
|
||||
*/
|
||||
public static long getConfigLongValue(ConfigType configType) {
|
||||
String value = getConfigStringValue(configType);
|
||||
|
||||
return Long.parseLong(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the boolean value of a configuration parameter.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.sismics.docs.core.util.authentication;
|
||||
|
||||
import com.sismics.docs.core.constant.ConfigType;
|
||||
import com.sismics.docs.core.constant.Constants;
|
||||
import com.sismics.docs.core.dao.ConfigDao;
|
||||
import com.sismics.docs.core.dao.UserDao;
|
||||
import com.sismics.docs.core.model.jpa.Config;
|
||||
import com.sismics.docs.core.model.jpa.User;
|
||||
import com.sismics.docs.core.util.ConfigUtil;
|
||||
import com.sismics.util.ClasspathScanner;
|
||||
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
|
||||
import org.apache.directory.api.ldap.model.entry.Attribute;
|
||||
import org.apache.directory.api.ldap.model.entry.Entry;
|
||||
import org.apache.directory.api.ldap.model.entry.Value;
|
||||
import org.apache.directory.api.ldap.model.message.SearchScope;
|
||||
import org.apache.directory.ldap.client.api.DefaultLdapConnectionFactory;
|
||||
import org.apache.directory.ldap.client.api.LdapConnectionConfig;
|
||||
import org.apache.directory.ldap.client.api.LdapConnectionPool;
|
||||
import org.apache.directory.ldap.client.api.PoolableLdapConnectionFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* LDAP authentication handler.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
@ClasspathScanner.Priority(50) // Before the internal database
|
||||
public class LdapAuthenticationHandler implements AuthenticationHandler {
|
||||
/**
|
||||
* Logger.
|
||||
*/
|
||||
private static final Logger log = LoggerFactory.getLogger(LdapAuthenticationHandler.class);
|
||||
|
||||
/**
|
||||
* LDAP connection pool.
|
||||
*/
|
||||
private static LdapConnectionPool pool;
|
||||
|
||||
/**
|
||||
* Reset the LDAP pool.
|
||||
*/
|
||||
public static void reset() {
|
||||
if (pool != null) {
|
||||
try {
|
||||
pool.close();
|
||||
} catch (Exception e) {
|
||||
// NOP
|
||||
}
|
||||
}
|
||||
pool = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the LDAP pool.
|
||||
*/
|
||||
private static void init() {
|
||||
ConfigDao configDao = new ConfigDao();
|
||||
Config ldapEnabled = configDao.getById(ConfigType.LDAP_ENABLED);
|
||||
if (pool != null || ldapEnabled == null || !Boolean.parseBoolean(ldapEnabled.getValue())) {
|
||||
return;
|
||||
}
|
||||
|
||||
LdapConnectionConfig config = new LdapConnectionConfig();
|
||||
config.setLdapHost(ConfigUtil.getConfigStringValue(ConfigType.LDAP_HOST));
|
||||
config.setLdapPort(ConfigUtil.getConfigIntegerValue(ConfigType.LDAP_PORT));
|
||||
config.setName(ConfigUtil.getConfigStringValue(ConfigType.LDAP_ADMIN_DN));
|
||||
config.setCredentials(ConfigUtil.getConfigStringValue(ConfigType.LDAP_ADMIN_PASSWORD));
|
||||
|
||||
DefaultLdapConnectionFactory factory = new DefaultLdapConnectionFactory(config);
|
||||
GenericObjectPool.Config poolConfig = new GenericObjectPool.Config();
|
||||
poolConfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
|
||||
poolConfig.maxWait = 500;
|
||||
pool = new LdapConnectionPool(new PoolableLdapConnectionFactory(factory), poolConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(String username, String password) {
|
||||
init();
|
||||
if (pool == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fetch and authenticate the user
|
||||
Entry userEntry;
|
||||
try {
|
||||
EntryCursor cursor = pool.getConnection().search(ConfigUtil.getConfigStringValue(ConfigType.LDAP_BASE_DN),
|
||||
ConfigUtil.getConfigStringValue(ConfigType.LDAP_FILTER).replace("USERNAME", username), SearchScope.SUBTREE);
|
||||
if (cursor.next()) {
|
||||
userEntry = cursor.get();
|
||||
pool.getConnection().bind(userEntry.getDn(), password);
|
||||
} else {
|
||||
// User not found
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error authenticating \"" + username + "\" using the LDAP", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
UserDao userDao = new UserDao();
|
||||
User user = userDao.getActiveByUsername(username);
|
||||
if (user == null) {
|
||||
// The user is valid but never authenticated, create the user now
|
||||
log.info("\"" + username + "\" authenticated for the first time, creating the internal user");
|
||||
user = new User();
|
||||
user.setRoleId(Constants.DEFAULT_USER_ROLE);
|
||||
user.setUsername(username);
|
||||
user.setPassword(UUID.randomUUID().toString()); // No authentication using the internal database
|
||||
Attribute mailAttribute = userEntry.get("mail");
|
||||
if (mailAttribute == null || mailAttribute.get() == null) {
|
||||
user.setEmail(ConfigUtil.getConfigStringValue(ConfigType.LDAP_DEFAULT_EMAIL));
|
||||
} else {
|
||||
Value<?> value = mailAttribute.get();
|
||||
user.setEmail(value.getString());
|
||||
}
|
||||
user.setStorageQuota(ConfigUtil.getConfigLongValue(ConfigType.LDAP_DEFAULT_STORAGE));
|
||||
try {
|
||||
userDao.create(user, "admin");
|
||||
} catch (Exception e) {
|
||||
log.error("Error while creating the internal user", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,5 @@ log4j.appender.MEMORY=com.sismics.util.log4j.MemoryAppender
|
||||
log4j.appender.MEMORY.size=1000
|
||||
|
||||
log4j.logger.com.sismics=INFO
|
||||
log4j.logger.org.hibernate=ERROR
|
||||
log4j.logger.org.hibernate=ERROR
|
||||
log4j.logger.org.apache.directory=ERROR
|
||||
Reference in New Issue
Block a user