X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=security%2Fruntime%2Forg.argeo.security.ldap%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fsecurity%2Fldap%2Fjcr%2FJcrUserDetailsContextMapper.java;h=6b166d5c5613dfd58483ccc2382758d40e2e5c1a;hb=7f23c34bcf51716cfb8f3853d47680035747052f;hp=2d9fb1c1adf05cecf42a85c3137602d2b70d4163;hpb=03db65bd74ce09b696a4c5af15a58df988e5368d;p=lgpl%2Fargeo-commons.git diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java index 2d9fb1c1a..6b166d5c5 100644 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java +++ b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java @@ -1,27 +1,29 @@ package org.argeo.security.ldap.jcr; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Random; import java.util.concurrent.Executor; import javax.jcr.Node; -import javax.jcr.Repository; import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; -import org.argeo.jcr.ArgeoJcrConstants; import org.argeo.jcr.ArgeoNames; -import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; import org.argeo.security.jcr.JcrUserDetails; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; import org.springframework.security.GrantedAuthority; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.providers.encoding.PasswordEncoder; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; @@ -42,19 +44,43 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, private Map propertyToAttributes = new HashMap(); private Executor systemExecutor; - private RepositoryFactory repositoryFactory; + private Session session; + + private PasswordEncoder passwordEncoder; + private final Random random; + + public JcrUserDetailsContextMapper() { + random = createRandom(); + } + + private static Random createRandom() { + try { + return SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + return new Random(System.currentTimeMillis()); + } + } public UserDetails mapUserFromContext(final DirContextOperations ctx, final String username, GrantedAuthority[] authorities) { - if (repositoryFactory == null) - throw new ArgeoException("No JCR repository factory registered"); + // if (repository == null) + // throw new ArgeoException("No JCR repository registered"); final StringBuffer userHomePathT = new StringBuffer(""); - systemExecutor.execute(new Runnable() { + Runnable action = new Runnable() { public void run() { String userHomepath = mapLdapToJcr(username, ctx); userHomePathT.append(userHomepath); } - }); + }; + + if (SecurityContextHolder.getContext().getAuthentication() == null) { + // authentication + systemExecutor.execute(action); + JcrUtils.logoutQuietly(session); + } else { + // authenticated user + action.run(); + } // password byte[] arr = (byte[]) ctx @@ -69,18 +95,25 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, /** @return path to the user home node */ protected String mapLdapToJcr(String username, DirContextOperations ctx) { - Session session = null; + // Session session = null; try { - Repository nodeRepo = JcrUtils.getRepositoryByAlias( - repositoryFactory, ArgeoJcrConstants.ALIAS_NODE); - session = nodeRepo.login(); + // Repository nodeRepo = JcrUtils.getRepositoryByAlias( + // repositoryFactory, ArgeoJcrConstants.ALIAS_NODE); + // session = nodeRepo.login(); Node userHome = JcrUtils.getUserHome(session, username); if (userHome == null) - userHome = createUserHome(session, username); + userHome = JcrUtils.createUserHome(session, homeBasePath, + username); String userHomePath = userHome.getPath(); - Node userProfile = userHome.hasNode(ARGEO_USER_PROFILE) ? userHome - .getNode(ARGEO_USER_PROFILE) : userHome - .addNode(ARGEO_USER_PROFILE); + Node userProfile = userHome.getNode(ARGEO_PROFILE); + if (userHome.hasNode(ARGEO_PROFILE)) { + userProfile = userHome.getNode(ARGEO_PROFILE); + } else { + userProfile = userHome.addNode(ARGEO_PROFILE); + userProfile.addMixin(NodeType.MIX_TITLE); + userProfile.addMixin(NodeType.MIX_CREATED); + userProfile.addMixin(NodeType.MIX_LAST_MODIFIED); + } for (String jcrProperty : propertyToAttributes.keySet()) ldapToJcr(userProfile, jcrProperty, ctx); session.save(); @@ -91,28 +124,10 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, JcrUtils.discardQuietly(session); throw new ArgeoException("Cannot synchronize JCR and LDAP", e); } finally { - session.logout(); + // JcrUtils.logoutQuietly(session); } } - protected Node createUserHome(Session session, String username) { - try { - Node userHome = JcrUtils.mkdirs(session, - usernameToHomePath(username)); - userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME); - userHome.setProperty(ARGEO_USER_ID, username); - return userHome; - } catch (RepositoryException e) { - throw new ArgeoException("Cannot create home node for user " - + username, e); - } - } - - protected String usernameToHomePath(String username) { - return homeBasePath + '/' + JcrUtils.firstCharsToPath(username, 2) - + '/' + username; - } - public void mapUserToContext(UserDetails user, final DirContextAdapter ctx) { if (!(user instanceof JcrUserDetails)) throw new ArgeoException("Unsupported user details: " @@ -120,31 +135,40 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, ctx.setAttributeValues("objectClass", userClasses); ctx.setAttributeValue(usernameAttribute, user.getUsername()); - ctx.setAttributeValue(passwordAttribute, user.getPassword()); + ctx.setAttributeValue(passwordAttribute, + encodePassword(user.getPassword())); final JcrUserDetails jcrUserDetails = (JcrUserDetails) user; - systemExecutor.execute(new Runnable() { - public void run() { - Session session = null; - try { - Repository nodeRepo = JcrUtils.getRepositoryByAlias( - repositoryFactory, ArgeoJcrConstants.ALIAS_NODE); - session = nodeRepo.login(); - Node userProfile = session.getNode(jcrUserDetails - .getHomePath() + '/' + ARGEO_USER_PROFILE); - for (String jcrProperty : propertyToAttributes.keySet()) - jcrToLdap(userProfile, jcrProperty, ctx); - if (log.isDebugEnabled()) - log.debug("Mapped " + userProfile + " to " - + ctx.getDn()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot synchronize JCR and LDAP", - e); - } finally { - session.logout(); - } - } - }); + // systemExecutor.execute(new Runnable() { + // public void run() { + // Session session = null; + try { + // Repository nodeRepo = JcrUtils.getRepositoryByAlias( + // repositoryFactory, ArgeoJcrConstants.ALIAS_NODE); + // session = nodeRepo.login(); + Node userProfile = session.getNode(jcrUserDetails.getHomePath() + + '/' + ARGEO_PROFILE); + for (String jcrProperty : propertyToAttributes.keySet()) + jcrToLdap(userProfile, jcrProperty, ctx); + if (log.isDebugEnabled()) + log.debug("Mapped " + userProfile + " to " + ctx.getDn()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot synchronize JCR and LDAP", e); + } finally { + // session.logout(); + } + // } + // }); + } + + protected String encodePassword(String password) { + if (!password.startsWith("{")) { + byte[] salt = new byte[16]; + random.nextBytes(salt); + return passwordEncoder.encodePassword(password, salt); + } else { + return password; + } } protected void ldapToJcr(Node userProfile, String jcrProperty, @@ -201,15 +225,15 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, this.homeBasePath = homeBasePath; } - public void register(RepositoryFactory repositoryFactory, - Map parameters) { - this.repositoryFactory = repositoryFactory; - } - - public void unregister(RepositoryFactory repositoryFactory, - Map parameters) { - this.repositoryFactory = null; - } + // public void register(RepositoryFactory repositoryFactory, + // Map parameters) { + // this.repositoryFactory = repositoryFactory; + // } + // + // public void unregister(RepositoryFactory repositoryFactory, + // Map parameters) { + // this.repositoryFactory = null; + // } public void setUsernameAttribute(String usernameAttribute) { this.usernameAttribute = usernameAttribute; @@ -223,4 +247,12 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, this.userClasses = userClasses; } + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + + public void setSession(Session session) { + this.session = session; + } + }