X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=security%2Fruntime%2Forg.argeo.security.jackrabbit%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fsecurity%2Fjackrabbit%2FArgeoSecurityManager.java;h=00c674580076d7bcbf7d6bdef5b2a343fc47ca6e;hb=5c83877a10b02faf5bc065c59250f31a0befe0f6;hp=1109980696d61d110aab683ddbde53f937286d4b;hpb=1d5afdce3e91054f07ddd3c98309c363b4cf1d46;p=lgpl%2Fargeo-commons.git diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java index 110998069..00c674580 100644 --- a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java +++ b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java @@ -17,26 +17,19 @@ package org.argeo.security.jackrabbit; import java.security.Principal; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import javax.jcr.Node; -import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFactory; -import javax.jcr.security.Privilege; import javax.security.auth.Subject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.api.security.JackrabbitAccessControlList; -import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager; -import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy; import org.apache.jackrabbit.api.security.user.Group; import org.apache.jackrabbit.api.security.user.User; import org.apache.jackrabbit.api.security.user.UserManager; @@ -44,14 +37,17 @@ import org.apache.jackrabbit.core.DefaultSecurityManager; import org.apache.jackrabbit.core.security.AnonymousPrincipal; import org.apache.jackrabbit.core.security.SecurityConstants; import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager; -import org.argeo.ArgeoException; -import org.argeo.jcr.JcrUtils; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; -/** Intermediary class in order to have a consistent naming in config files. */ +/** Integrates Spring Security and Jackrabbit Security user and roles. */ public class ArgeoSecurityManager extends DefaultSecurityManager { - private Log log = LogFactory.getLog(ArgeoSecurityManager.class); + private final static Log log = LogFactory + .getLog(ArgeoSecurityManager.class); + + /** TODO? use a bounded buffer */ + private Map userRolesCache = Collections + .synchronizedMap(new HashMap()); /** * Since this is called once when the session is created, we take the @@ -61,8 +57,6 @@ public class ArgeoSecurityManager extends DefaultSecurityManager { @Override public String getUserID(Subject subject, String workspaceName) throws RepositoryException { - long begin = System.currentTimeMillis(); - if (log.isTraceEnabled()) log.trace(subject); // skip anonymous user (no rights) @@ -72,25 +66,60 @@ public class ArgeoSecurityManager extends DefaultSecurityManager { if (!subject.getPrincipals(ArgeoSystemPrincipal.class).isEmpty()) return super.getUserID(subject, workspaceName); + // retrieve Spring authentication from JAAS + // TODO? use Spring Security context holder Authentication authen; Set authens = subject .getPrincipals(Authentication.class); - if (authens.size() == 0) - throw new ArgeoException("No Spring authentication found in " - + subject); - else + String userId; + if (authens.size() == 0) { + // make sure that logged-in user has a Principal, useful for testing + // using an admin user + userId = super.getUserID(subject, workspaceName); + UserManager systemUm = getSystemUserManager(null); + if (systemUm.getAuthorizable(userId) == null) + systemUm.createUser(userId, ""); + } else {// Spring Security authen = authens.iterator().next(); - UserManager systemUm = getSystemUserManager(workspaceName); + userId = authen.getName(); + StringBuffer roles = new StringBuffer(""); + GrantedAuthority[] authorities = authen.getAuthorities(); + for (GrantedAuthority ga : authorities) { + roles.append(ga.toString()); + } + + // do not sync if not changed + if (userRolesCache.containsKey(userId) + && userRolesCache.get(userId).equals(roles.toString())) + return userId; + + // sync Spring and Jackrabbit + // workspace is irrelevant here + UserManager systemUm = getSystemUserManager(null); + syncSpringAndJackrabbitSecurity(systemUm, authen); + userRolesCache.put(userId, roles.toString()); + } + return userId; + } + + /** + * Make sure that the Jackrabbit security model contains this user and its + * granted authorities + */ + static void syncSpringAndJackrabbitSecurity(UserManager systemUm, + Authentication authen) throws RepositoryException { + long begin = System.currentTimeMillis(); String userId = authen.getName(); User user = (User) systemUm.getAuthorizable(userId); if (user == null) { user = systemUm.createUser(userId, authen.getCredentials() .toString(), authen, null); - JcrUtils.createUserHomeIfNeeded(getSystemSession(), userId); - getSystemSession().save(); - setSecurityHomeAuthorizations(user); + // SecurityJcrUtils.createUserHomeIfNeeded(getSystemSession(), + // userId); + // getSystemSession().save(); + // setSecurityHomeAuthorizations(user); log.info(userId + " added as " + user); } @@ -118,51 +147,51 @@ public class ArgeoSecurityManager extends DefaultSecurityManager { log.trace("Spring and Jackrabbit Security synchronized for user " + userId + " in " + (System.currentTimeMillis() - begin) + " ms"); - return userId; } - protected synchronized void setSecurityHomeAuthorizations(User user) { - // give read privileges on user security home - String userId = ""; - try { - userId = user.getID(); - Node userHome = JcrUtils.getUserHome(getSystemSession(), userId); - if (userHome == null) - throw new ArgeoException("No security home available for user " - + userId); - - String path = userHome.getPath(); - Principal principal = user.getPrincipal(); - - JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) getSystemSession() - .getAccessControlManager(); - JackrabbitAccessControlPolicy[] ps = acm - .getApplicablePolicies(principal); - if (ps.length == 0) { - // log.warn("No ACL found for " + user); - return; - } - - JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0]; - - // add entry - Privilege[] privileges = new Privilege[] { acm - .privilegeFromName(Privilege.JCR_READ) }; - Map restrictions = new HashMap(); - ValueFactory vf = getSystemSession().getValueFactory(); - restrictions.put("rep:nodePath", - vf.createValue(path, PropertyType.PATH)); - restrictions.put("rep:glob", vf.createValue("*")); - list.addEntry(principal, privileges, true /* allow or deny */, - restrictions); - } catch (Exception e) { - e.printStackTrace(); - throw new ArgeoException( - "Cannot set authorization on security home for " + userId - + ": " + e.getMessage()); - } - - } + // protected synchronized void setSecurityHomeAuthorizations(User user) { + // // give read privileges on user security home + // String userId = ""; + // try { + // userId = user.getID(); + // Node userHome = SecurityJcrUtils.getUserHome(getSystemSession(), userId); + // if (userHome == null) + // throw new ArgeoException("No security home available for user " + // + userId); + // + // String path = userHome.getPath(); + // Principal principal = user.getPrincipal(); + // + // JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) + // getSystemSession() + // .getAccessControlManager(); + // JackrabbitAccessControlPolicy[] ps = acm + // .getApplicablePolicies(principal); + // if (ps.length == 0) { + // // log.warn("No ACL found for " + user); + // return; + // } + // + // JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0]; + // + // // add entry + // Privilege[] privileges = new Privilege[] { acm + // .privilegeFromName(Privilege.JCR_READ) }; + // Map restrictions = new HashMap(); + // ValueFactory vf = getSystemSession().getValueFactory(); + // restrictions.put("rep:nodePath", + // vf.createValue(path, PropertyType.PATH)); + // restrictions.put("rep:glob", vf.createValue("*")); + // list.addEntry(principal, privileges, true /* allow or deny */, + // restrictions); + // } catch (Exception e) { + // e.printStackTrace(); + // throw new ArgeoException( + // "Cannot set authorization on security home for " + userId + // + ": " + e.getMessage()); + // } + // + // } @Override protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {