[dna-commits] DNA SVN: r877 - in trunk: dna-jcr/src/main/java/org/jboss/dna/jcr and 1 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Mon May 4 13:32:45 EDT 2009


Author: rhauch
Date: 2009-05-04 13:32:44 -0400 (Mon, 04 May 2009)
New Revision: 877

Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
   trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
Log:
DNA-371 No Default JAAS Implementation

Applied the patch, which improves ExecutionContext by allowing the creation of a context using the username and password for JAAS authentication, and which changes JcrRepository to use this approach when authenticating with SimpleCredentials.  There still is no test for this, but that should be added subsequently.

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java	2009-05-04 17:21:43 UTC (rev 876)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java	2009-05-04 17:32:44 UTC (rev 877)
@@ -23,10 +23,16 @@
  */
 package org.jboss.dna.graph;
 
+import java.io.IOException;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.Configuration;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
@@ -413,11 +419,33 @@
      */
     public ExecutionContext with( String name,
                                   CallbackHandler callbackHandler ) throws LoginException {
-        return new ExecutionContext(this, new LoginContext(name, callbackHandler));
+        LoginContext loginContext = new LoginContext(name, callbackHandler);
+        loginContext.login();
+        
+        return new ExecutionContext(this, loginContext);
     }
 
     /**
      * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied
+     * {@link Configuration#getAppConfigurationEntry(String) application configuration name} and a {@link CallbackHandler JAAS
+     * callback handler} to create a new {@link LoginContext login context} with the given user ID and password.
+     * 
+     * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
+     * @param userId the user ID to use for authentication
+     * @param password the password to use for authentication
+     * @return the execution context that is identical with this execution context, but with a different security context; never
+     *         null
+     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
+     *         <code>callbackHandler</code> is null
+     */
+    public ExecutionContext with( String name,
+                                  String userId,
+                                  char[] password ) throws LoginException {
+        return this.with(name, new UserPasswordCallbackHandler(userId, password));
+    }
+
+    /**
+     * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied
      * {@link Configuration#getAppConfigurationEntry(String) application configuration name}, a {@link Subject JAAS subject}, and
      * a {@link CallbackHandler JAAS callback handler} (used to handle authentication callbacks).
      * 
@@ -434,7 +462,10 @@
     public ExecutionContext with( String name,
                                   Subject subject,
                                   CallbackHandler callbackHandler ) throws LoginException {
-        return new ExecutionContext(this, new LoginContext(name, subject, callbackHandler));
+        LoginContext loginContext = new LoginContext(name, subject, callbackHandler);
+        loginContext.login();
+        
+        return new ExecutionContext(this, loginContext);
     }
 
     /**
@@ -471,4 +502,82 @@
         // namespaceRegistry.register("dnadtd", "http://www.jboss.org/dna/dtd/1.0");
         // namespaceRegistry.register("dnaxml", "http://www.jboss.org/dna/xml/1.0");
     }
+
+    /**
+     * A simple {@link CallbackHandler callback handler} implementation that attempts to provide a user ID and password to any
+     * callbacks that it handles.
+     */
+    protected final class UserPasswordCallbackHandler implements CallbackHandler {
+
+        private static final boolean LOG_TO_CONSOLE = false;
+
+        private final String userId;
+        private final char[] password;
+
+        protected UserPasswordCallbackHandler( String userId,
+                                               char[] password ) {
+            this.userId = userId;
+            this.password = password;
+        }
+
+        /**
+         * 
+         * {@inheritDoc}
+         *
+         * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
+         */
+        public void handle( Callback[] callbacks ) throws UnsupportedCallbackException, IOException {
+            for (int i = 0; i < callbacks.length; i++) {
+                if (callbacks[i] instanceof TextOutputCallback) {
+
+                    // display the message according to the specified type
+                    TextOutputCallback toc = (TextOutputCallback)callbacks[i];
+                    if (!LOG_TO_CONSOLE) {
+                        continue;
+                    }
+
+                    switch (toc.getMessageType()) {
+                        case TextOutputCallback.INFORMATION:
+                            System.out.println(toc.getMessage());
+                            break;
+                        case TextOutputCallback.ERROR:
+                            System.out.println("ERROR: " + toc.getMessage());
+                            break;
+                        case TextOutputCallback.WARNING:
+                            System.out.println("WARNING: " + toc.getMessage());
+                            break;
+                        default:
+                            throw new IOException("Unsupported message type: " + toc.getMessageType());
+                    }
+
+                } else if (callbacks[i] instanceof NameCallback) {
+
+                    // prompt the user for a username
+                    NameCallback nc = (NameCallback)callbacks[i];
+
+                    if (LOG_TO_CONSOLE) {
+                        // ignore the provided defaultName
+                        System.out.print(nc.getPrompt());
+                        System.out.flush();
+                    }
+
+                    nc.setName(this.userId);
+
+                } else if (callbacks[i] instanceof PasswordCallback) {
+
+                    // prompt the user for sensitive information
+                    PasswordCallback pc = (PasswordCallback)callbacks[i];
+                    if (LOG_TO_CONSOLE) {
+                        System.out.print(pc.getPrompt());
+                        System.out.flush();
+                    }
+                    pc.setPassword(this.password);
+
+                } else {
+                    throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+                }
+            }
+
+        }
+    }
 }

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-05-04 17:21:43 UTC (rev 876)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-05-04 17:32:44 UTC (rev 877)
@@ -36,6 +36,7 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
+import javax.security.auth.login.Configuration;
 import javax.security.auth.login.LoginContext;
 import net.jcip.annotations.ThreadSafe;
 import org.jboss.dna.common.util.CheckArg;
@@ -84,6 +85,11 @@
          * @see DefaultOptions#PROJECT_NODE_TYPES
          */
         PROJECT_NODE_TYPES,
+        /**
+         * The {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name} that specifies which
+         * login modules should be used to validate credentials.
+         */
+        JAAS_LOGIN_CONFIG_NAME,
     }
 
     /**
@@ -94,6 +100,11 @@
          * The default value for the {@link Options#PROJECT_NODE_TYPES} option is {@value} .
          */
         public static final String PROJECT_NODE_TYPES = Boolean.FALSE.toString();
+
+        /**
+         * The default value for the {@link Options#JAAS_LOGIN_CONFIG_NAME} option is {@value} .
+         */
+        public static final String JAAS_LOGIN_CONFIG_NAME = "dna-jcr";
     }
 
     /**
@@ -105,6 +116,7 @@
         // Initialize the unmodifiable map of default options ...
         EnumMap<Options, String> defaults = new EnumMap<Options, String>(Options.class);
         defaults.put(Options.PROJECT_NODE_TYPES, DefaultOptions.PROJECT_NODE_TYPES);
+        defaults.put(Options.JAAS_LOGIN_CONFIG_NAME, DefaultOptions.JAAS_LOGIN_CONFIG_NAME);
         DEFAULT_OPTIONS = Collections.<Options, String>unmodifiableMap(defaults);
     }
 
@@ -291,7 +303,8 @@
      * 
      * @throws IllegalArgumentException if <code>credentials</code> is not <code>null</code> but:
      *         <ul>
-     *         <li>provides neither a <code>getLoginContext()</code> nor a <code>getAccessControlContext()</code> method.</li>
+     *         <li>provides neither a <code>getLoginContext()</code> nor a <code>getAccessControlContext()</code> method and is
+     *         not an instance of {@code SimpleCredentials}.</li>
      *         <li>provides a <code>getLoginContext()</code> method that doesn't return a {@link LoginContext}.
      *         <li>provides a <code>getLoginContext()</code> method that returns a <code>null</code> {@link LoginContext}.
      *         <li>does not provide a <code>getLoginContext()</code> method, but provides a <code>getAccessControlContext()</code>
@@ -336,8 +349,16 @@
                         }
                         execContext = executionContext.create(accessControlContext);
                     } catch (NoSuchMethodException error2) {
-                        throw new IllegalArgumentException(JcrI18n.credentialsMustProvideJaasMethod.text(credentials.getClass()),
-                                                           error2);
+                        if (credentials instanceof SimpleCredentials) {
+                            SimpleCredentials simple = (SimpleCredentials)credentials;
+                            execContext = executionContext.with(options.get(Options.JAAS_LOGIN_CONFIG_NAME),
+                                                                simple.getUserID(),
+                                                                simple.getPassword());
+                        } else {
+                            throw new IllegalArgumentException(
+                                                               JcrI18n.credentialsMustProvideJaasMethod.text(credentials.getClass()),
+                                                               error2);
+                        }
                     }
                 }
             } catch (RuntimeException error) {

Modified: trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties	2009-05-04 17:21:43 UTC (rev 876)
+++ trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties	2009-05-04 17:32:44 UTC (rev 877)
@@ -42,4 +42,12 @@
 javax.jcr.tck.NodeTest.testRemoveMandatoryNode.nodename3=dnatest\:mandatoryChild
 javax.jcr.tck.NodeTest.testSaveContstraintViolationException.nodetype2=dnatest\:nodeWithMandatoryProperty
 javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype2=dnatest\:unorderableUnstructured
-javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype3=dnatest\:unorderableUnstructured
\ No newline at end of file
+javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOperationException.nodetype3=dnatest\:unorderableUnstructured
+
+# Test users
+javax.jcr.tck.superuser.name=superuser
+javax.jcr.tck.superuser.pwd=superuser
+javax.jcr.tck.readwrite.name=readwrite
+javax.jcr.tck.readwrite.pwd=readwrite
+javax.jcr.tck.readonly.name=readonly
+javax.jcr.tck.readonly.pwd=readonly
\ No newline at end of file




More information about the dna-commits mailing list