You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2008/05/22 09:11:50 UTC

svn commit: r659024 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/ main/java/org/apache/jackrabbit/core/security/ main/java/org/apache/jackrabbit/core/security/simple/ test/java/org/apache/jackrabbit/core/security/user/

Author: angela
Date: Thu May 22 00:11:50 2008
New Revision: 659024

URL: http://svn.apache.org/viewvc?rev=659024&view=rev
Log:
JCR-1588: JSR 283 Access Control (work in progress)
JCR-1622 - Session.getUserID returns first principal in the set obtained from Subject.getPrincipals()

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java?rev=659024&r1=659023&r2=659024&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/DefaultSecurityManager.java Thu May 22 00:11:50 2008
@@ -21,6 +21,7 @@
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.core.config.AccessManagerConfig;
 import org.apache.jackrabbit.core.config.BeanConfig;
 import org.apache.jackrabbit.core.config.LoginModuleConfig;
@@ -43,6 +44,7 @@
 import org.apache.jackrabbit.core.security.principal.PrincipalProvider;
 import org.apache.jackrabbit.core.security.principal.PrincipalProviderRegistry;
 import org.apache.jackrabbit.core.security.principal.ProviderRegistryImpl;
+import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
 import org.apache.jackrabbit.core.security.user.UserManagerImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -53,6 +55,7 @@
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
 import javax.security.auth.Subject;
 import java.security.Principal;
 import java.util.HashMap;
@@ -318,6 +321,47 @@
     }
 
     /**
+     * @see JackrabbitSecurityManager#getUserID(Subject)
+     */
+    public String getUserID(Subject subject) throws RepositoryException {
+        /* shortcut if the subject contains the AdminPrincipal in which case
+           the userID is already known. */
+        if (!subject.getPrincipals(AdminPrincipal.class).isEmpty()) {
+            return adminId;
+        }
+        /*
+         Retrieve userID from the subject.
+         Since the subject may contain multiple principals and the principal
+         name must not be equals to the UserID by definition, the userID
+         may either be obtained from the login-credentials or from the
+         user manager. in the latter case the set of principals present with
+         the specified subject is used to search for the user.
+        */
+        String uid = null;
+        // try simple access to userID over SimpleCredentials first.
+        Iterator creds = subject.getPublicCredentials(SimpleCredentials.class).iterator();
+        if (creds.hasNext()) {
+            SimpleCredentials sc = (SimpleCredentials) creds.next();
+            uid = sc.getUserID();
+        } else {
+            // no SimpleCredentials: retrieve authorizables corresponding to
+            // a non-group principal. the first one present is used to determine
+            // the userID.
+            for (Iterator it = subject.getPrincipals().iterator(); it.hasNext();) {
+                Principal p = (Principal) it.next();
+                if (!(p instanceof Group)) {
+                    Authorizable authorz = systemUserManager.getAuthorizable(p);
+                    if (authorz != null && !authorz.isGroup()) {
+                        uid = ((User) authorz).getID();
+                        break;
+                    }
+                }
+            }
+        }
+        return uid;
+    }
+
+    /**
      * Creates an AuthContext for the given {@link Credentials} and
      * {@link Subject}.<br>
      * This includes selection of application specific LoginModules and

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=659024&r1=659023&r2=659024&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Thu May 22 00:11:50 2008
@@ -260,23 +260,7 @@
         this.rep = rep;
         this.subject = subject;
 
-        /*
-         Retrieve userID from the subject.
-         Since the subject may contain multiple principals and the principal
-         name must not be equals to the UserID by definition, the proper way
-         is to check for known credentials the provide the correct userID.
-         The specification explicitely defines the UserID to be related to
-         the credentials and allows 'null' values in case the credentials do
-         not reveal a userID.
-         TODO: eval alternative approach via UserManager
-        */
-        String uid = null;
-        Iterator creds = subject.getPublicCredentials(SimpleCredentials.class).iterator();
-        if (creds.hasNext()) {
-            SimpleCredentials sc = (SimpleCredentials) creds.next();
-            uid = sc.getUserID();
-        }
-        userId = uid;
+        userId = retrieveUserId(subject);
 
         namePathResolver = new DefaultNamePathResolver(this, true);
         ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), this, rep.getDataStore());
@@ -291,6 +275,15 @@
     }
 
     /**
+     * Retrieve the userID from the specified subject.
+     *
+     * @return the userID.
+     */
+    protected String retrieveUserId(Subject subject) throws RepositoryException {
+        return rep.getSecurityManager().getUserID(subject);
+    }
+
+    /**
      * Create the session item state manager.
      *
      * @return session item state manager

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java?rev=659024&r1=659023&r2=659024&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java Thu May 22 00:11:50 2008
@@ -71,6 +71,15 @@
     }
 
     /**
+     * Always returns the name of the <code>SystemPrincipal</code>.
+     *
+     * @return the name of <code>SystemPrincipal</code>.
+     */
+    protected String retrieveUserId(Subject subject) throws RepositoryException {
+        return new SystemPrincipal().getName();
+    }
+
+    /**
      * {@inheritDoc}
      * <p/>
      * Overridden in order to create custom access manager
@@ -156,7 +165,7 @@
         /**
          * Always returns true.
          *
-         * @see AccessManager#isGranted(Path, Name, int) 
+         * @see AccessManager#isGranted(Path, Name, int)
          */
         public boolean isGranted(Path parentPath, Name childName, int permissions) throws RepositoryException {
             // allow everything

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java?rev=659024&r1=659023&r2=659024&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/JackrabbitSecurityManager.java Thu May 22 00:11:50 2008
@@ -100,4 +100,13 @@
      */
     public UserManager getUserManager(Session session) throws RepositoryException;
 
+    /**
+     * Retrieve the id to be displayed upon {@link Session#getUserID()} for
+     * the specified subject.
+     *
+     * @param subject
+     * @return userID to be displayed upon {@link Session#getUserID()}.
+     * @throws RepositoryException
+     */
+    public String getUserID(Subject subject) throws RepositoryException;
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java?rev=659024&r1=659023&r2=659024&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java Thu May 22 00:11:50 2008
@@ -47,6 +47,7 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.SimpleCredentials;
 import javax.security.auth.Subject;
 import java.security.Principal;
 import java.security.acl.Group;
@@ -56,6 +57,7 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.Iterator;
 
 /**
  * <code>SimpleSecurityManager</code>: simple implementation ignoring both
@@ -209,6 +211,31 @@
     }
 
     /**
+     * @see JackrabbitSecurityManager#getUserID(Subject)
+     */
+    public String getUserID(Subject subject) throws RepositoryException {
+        String uid = null;
+        // if SimpleCredentials are present, the UserID can easily be retrieved.
+        Iterator creds = subject.getPublicCredentials(SimpleCredentials.class).iterator();
+        if (creds.hasNext()) {
+            SimpleCredentials sc = (SimpleCredentials) creds.next();
+            uid = sc.getUserID();
+        } else {
+            // no SimpleCredentials: assume that UserID and principal name
+            // are the same (not totally correct) and thus return the name
+            // of the first non-group principal.
+            for (Iterator it = subject.getPrincipals().iterator(); it.hasNext();) {
+                Principal p = (Principal) it.next();
+                if (!(p instanceof Group)) {
+                    uid = p.getName();
+                    break;
+                }
+            }
+        }
+        return uid;
+    }
+
+    /**
      * Creates an AuthContext for the given {@link Credentials} and
      * {@link Subject}.<br>
      * This includes selection of applicatoin specific LoginModules and

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java?rev=659024&r1=659023&r2=659024&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserManagerImplTest.java Thu May 22 00:11:50 2008
@@ -126,19 +126,50 @@
         }
     }
 
+    public void testUserIDFromSession() throws RepositoryException {
+        Principal p = getTestPrincipal();
+        User u = null;
+        Session uSession = null;
+        try {
+            String uid = p.getName();
+            String pw = buildPassword(p);
+            u = userMgr.createUser(uid, pw);
+
+            uSession = superuser.getRepository().login(new SimpleCredentials(uid, pw.toCharArray()));
+            assertEquals(u.getID(), uSession.getUserID());
+        } finally {
+            if (uSession != null) {
+                uSession.logout();
+            }
+            if (u != null) {
+                u.remove();
+            }
+        }
+    }
+
     public void testCreateUserIdDifferentFromPrincipalName() throws RepositoryException {
         Principal p = getTestPrincipal();
         String uid = getTestUserId(p);
+        String pw = buildPassword(uid, true);
 
         User u = null;
+        Session uSession = null;
         try {
-            u = userMgr.createUser(uid, buildPassword(uid, true), p, null);
+            u = userMgr.createUser(uid, pw, p, null);
 
             String msg = "Creating a User with principal-name distinct from Principal-name must succeed as long as both are unique.";
             assertEquals(msg, u.getID(), uid);
             assertEquals(msg, p.getName(), u.getPrincipal().getName());
             assertFalse(msg, u.getID().equals(u.getPrincipal().getName()));
+
+            // make sure the userID exposed by a Session corresponding to that
+            // user is equal to the users ID.
+            uSession = superuser.getRepository().login(new SimpleCredentials(uid, pw.toCharArray()));
+            assertEquals(uid, uSession.getUserID());
         } finally {
+            if (uSession != null) {
+                uSession.logout();
+            }
             if (u != null) {
                 u.remove();
             }