JndiLoginModule für LDAP

git-svn-id: https://svn.libreccm.org/ccm/trunk@6267 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2019-10-15 18:18:37 +00:00
parent c89fe0a5b5
commit 24092bc982
1 changed files with 171 additions and 0 deletions

View File

@ -0,0 +1,171 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.arsdigita.kernel.security;
import org.apache.log4j.Logger;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.Hashtable;
import java.util.Map;
import javax.naming.AuthenticationException;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import com.arsdigita.kernel.UserAuthentication;
import java.math.BigDecimal;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class JndiLoginModule extends PasswordLoginModule implements LoginModule {
private static final Logger LOGGER = Logger.getLogger(JndiLoginModule.class);
private Subject subject;
private CallbackHandler callbackHandler;
private Map<String, ?> sharedState;
private Map<String, ?> options;
private String username;
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public void initialize(final Subject subject,
final CallbackHandler callbackHandler,
Map sharedState,
Map options) {
super.initialize(subject, callbackHandler, sharedState, options);
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;
}
@Override
public boolean commit() throws LoginException {
LOGGER.debug("Commit");
final UserAuthentication auth = UserAuthentication
.retrieveForSSOlogin(username);
final BigDecimal userId = auth.getUser().getID();
subject.getPrincipals().add(new PartyPrincipal(userId));
return true;
}
@Override
public boolean abort() throws LoginException {
LOGGER.debug("Aborting");
return true;
}
@Override
public boolean logout() throws LoginException {
LOGGER.debug("Logout");
return true;
}
@Override
protected void checkPassword(final String username, final char[] password)
throws LoginException {
this.username = username;
final Hashtable<String, Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, options.get("connectionURL"));
env.put(Context.SECURITY_AUTHENTICATION, "none");
try {
final DirContext context = new InitialDirContext(env);
final String userBase = (String) options.get("userBase");
final MessageFormat userSearchFormat = new MessageFormat(
(String) options.get("userSearch")
);
final String filter = userSearchFormat
.format(new String[]{username});
final SearchControls searchControls = new SearchControls();
final NamingEnumeration<SearchResult> results = context.search(
userBase, filter, searchControls
);
if (!results.hasMore()) {
throw new FailedLoginException("Bad Username / password");
}
final SearchResult result = results.next();
final String resultName = result.getName();
final Name name;
final NameParser parser = context.getNameParser("");
if (result.isRelative()) {
final Name contextName = parser.parse(
context.getNameInNamespace()
);
final Name baseName = parser.parse(userBase);
final Name entryName = parser.parse(
new CompositeName(resultName).get(0)
);
name = contextName
.addAll(baseName)
.addAll(entryName);
} else {
try {
final URI userNameUri = new URI(resultName);
final String pathComponent = userNameUri.getPath();
if (pathComponent.length() < 1) {
throw new KernelLoginException(
"Unparsable absolute name."
);
}
name = parser.parse(pathComponent.substring(1));
} catch (URISyntaxException ex) {
throw new KernelLoginException(ex);
}
}
final String userDn = name.toString();
context.addToEnvironment(Context.SECURITY_PRINCIPAL, userDn);
context.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
try {
context.getAttributes("", null);
} catch(AuthenticationException ex) {
LOGGER.info("LDAP login failed.");
throw new FailedLoginException(
"Bad username / password for LDAP"
);
}
} catch (NamingException ex) {
throw new KernelLoginException(ex);
}
LOGGER.debug("Successfully checked password for LDAP.");
}
}