X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=security%2Fruntime%2Forg.argeo.security.ldap%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fsecurity%2Fldap%2Fjcr%2FJcrUserDetailsContextMapper.java;h=03260bfb7d02f855b7d6ca0e2013e26e658da46a;hb=a39a9b0e7ad6a44b4fab9db2d2a2224badd4062d;hp=86c788a448e5188f8afd6902188e955b492bf2fb;hpb=802beab5459c8da4970215886babb45d968e4639;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 86c788a44..03260bfb7 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,22 +1,31 @@ +/* + * Copyright (C) 2007-2012 Mathieu Baudier + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.argeo.security.ldap.jcr; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; +import java.util.UUID; import javax.jcr.Node; import javax.jcr.Repository; import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; import javax.jcr.Session; -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.JcrUtils; -import org.argeo.security.SystemExecutionService; +import org.argeo.jcr.UserJcrUtils; import org.argeo.security.jcr.JcrUserDetails; import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; @@ -24,161 +33,64 @@ import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; -/** - * Maps LDAP attributes and JCR properties. This class is meant to be robust, - * checks of which values should be mandatory should be performed at a higher - * level. - */ -public class JcrUserDetailsContextMapper implements UserDetailsContextMapper { - private final static Log log = LogFactory - .getLog(JcrUserDetailsContextMapper.class); - - private Map propertyToAttributes = new HashMap(); - private SystemExecutionService systemExecutionService; - private String homeBasePath = "/home"; - private RepositoryFactory repositoryFactory; - - public UserDetails mapUserFromContext(final DirContextOperations ctx, - final String username, GrantedAuthority[] authorities) { - if (repositoryFactory == null) - throw new ArgeoException("No JCR repository factory registered"); - final String userHomePath = usernameToHomePath(username); - systemExecutionService.executeAsSystem(new Runnable() { - public void run() { - Session session = null; - try { - Repository nodeRepo = JcrUtils.getRepositoryByAlias( - repositoryFactory, ArgeoJcrConstants.ALIAS_NODE); - session = nodeRepo.login(); - Node userProfile = JcrUtils.mkdirs(session, userHomePath - + '/' + ArgeoNames.ARGEO_USER_PROFILE); - for (String jcrProperty : propertyToAttributes.keySet()) - ldapToJcr(userProfile, jcrProperty, ctx); - session.save(); - if (log.isDebugEnabled()) - log.debug("Mapped " + ctx.getDn() + " to " - + userProfile); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot synchronize JCR and LDAP", - e); - } finally { - session.logout(); - } - } - }); +/** @deprecated Read only mapping from LDAP to user details */ +@Deprecated +public class JcrUserDetailsContextMapper implements UserDetailsContextMapper, + ArgeoNames { + /** Admin session on the security workspace */ + private Session securitySession; + private Repository repository; + private String securityWorkspace = "security"; - // password - byte[] arr = (byte[]) ctx.getAttributeSortedStringSet("userPassword") - .first(); - JcrUserDetails userDetails = new JcrUserDetails(userHomePath, username, - new String(arr), true, true, true, true, authorities); - Arrays.fill(arr, (byte) 0); - return userDetails; - } - - public void mapUserToContext(UserDetails user, final DirContextAdapter ctx) { - if (!(user instanceof JcrUserDetails)) - throw new ArgeoException("Unsupported user details: " - + user.getClass()); - - ctx.setAttributeValues("objectClass", new String[] { "inetOrgPerson" }); - ctx.setAttributeValue("uid", user.getUsername()); - ctx.setAttributeValue("userPassword", user.getPassword()); - - final JcrUserDetails jcrUserDetails = (JcrUserDetails) user; - systemExecutionService.executeAsSystem(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() - + '/' - + ArgeoNames.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(); - } - } - }); - } - - protected String usernameToHomePath(String username) { - return homeBasePath + '/' + JcrUtils.firstCharsToPath(username, 2) - + '/' + username; - } - - protected void ldapToJcr(Node userProfile, String jcrProperty, - DirContextOperations ctx) { + public void init() { try { - String ldapAttribute; - if (propertyToAttributes.containsKey(jcrProperty)) - ldapAttribute = propertyToAttributes.get(jcrProperty); - else - throw new ArgeoException( - "No LDAP attribute mapped for JCR proprty " - + jcrProperty); - - String value = ctx.getStringAttribute(ldapAttribute); - if (value == null) - return; - userProfile.setProperty(jcrProperty, value); - } catch (Exception e) { - throw new ArgeoException("Cannot map JCR property " + jcrProperty - + " from LDAP", e); + securitySession = repository.login(securityWorkspace); + } catch (RepositoryException e) { + JcrUtils.logoutQuietly(securitySession); + throw new ArgeoException( + "Cannot initialize LDAP/JCR user details context mapper", e); } } - protected void jcrToLdap(Node userProfile, String jcrProperty, - DirContextOperations ctx) { - try { - if (!userProfile.hasProperty(jcrProperty)) - return; - String value = userProfile.getProperty(jcrProperty).getString(); - - String ldapAttribute; - if (propertyToAttributes.containsKey(jcrProperty)) - ldapAttribute = propertyToAttributes.get(jcrProperty); - else - throw new ArgeoException( - "No LDAP attribute mapped for JCR proprty " - + jcrProperty); - ctx.setAttributeValue(ldapAttribute, value); - } catch (Exception e) { - throw new ArgeoException("Cannot map JCR property " + jcrProperty - + " from LDAP", e); - } + public void destroy() { + JcrUtils.logoutQuietly(securitySession); } - public void setPropertyToAttributes(Map propertyToAttributes) { - this.propertyToAttributes = propertyToAttributes; - } + /** Called during authentication in order to retrieve user details */ + public UserDetails mapUserFromContext(final DirContextOperations ctx, + final String username, GrantedAuthority[] authorities) { + if (ctx == null) + throw new ArgeoException("No LDAP information for user " + username); + Node userHome = UserJcrUtils.getUserHome(securitySession, username); + if (userHome == null) + throw new ArgeoException("No JCR information for user " + username); - public void setSystemExecutionService( - SystemExecutionService systemExecutionService) { - this.systemExecutionService = systemExecutionService; - } + // password + // SortedSet passwordAttributes = ctx + // .getAttributeSortedStringSet(passwordAttribute); + // String password; + // if (passwordAttributes == null || passwordAttributes.size() == 0) { + // throw new ArgeoException("No password found for user " + username); + // } else { + // byte[] arr = (byte[]) passwordAttributes.first(); + // password = new String(arr); + // // erase password + // Arrays.fill(arr, (byte) 0); + // } - public void setHomeBasePath(String homeBasePath) { - this.homeBasePath = homeBasePath; + try { + // we don't have access to password, so let's not pretend + String password = UUID.randomUUID().toString(); + return new JcrUserDetails(userHome.getNode(ARGEO_PROFILE), + password, authorities); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot retrieve user details for " + + username, e); + } } - public void register(RepositoryFactory repositoryFactory, - Map parameters) { - this.repositoryFactory = repositoryFactory; + public void mapUserToContext(UserDetails user, final DirContextAdapter ctx) { + throw new UnsupportedOperationException("LDAP access is read-only"); } - public void unregister(RepositoryFactory repositoryFactory, - Map parameters) { - this.repositoryFactory = null; - } }