Index: dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java (revision 982) +++ dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java (working copy) @@ -23,26 +23,14 @@ */ 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; -import javax.security.auth.spi.LoginModule; import net.jcip.annotations.Immutable; import org.jboss.dna.common.component.ClassLoaderFactory; import org.jboss.dna.common.component.StandardClassLoaderFactory; import org.jboss.dna.common.util.CheckArg; import org.jboss.dna.common.util.Logger; -import org.jboss.dna.common.util.Reflection; import org.jboss.dna.graph.connector.federation.FederatedLexicon; import org.jboss.dna.graph.mimetype.ExtensionBasedMimeTypeDetector; import org.jboss.dna.graph.mimetype.MimeTypeDetector; @@ -64,7 +52,7 @@ * ExecutionContext instances are {@link Immutable immutable}, so components may hold onto references to them without concern of * those contexts changing. Contexts may be used to create other contexts that vary the environment and/or security context. For * example, an ExecutionContext could be used to create another context that references the same {@link #getNamespaceRegistry() - * namespace registry} but which has a different {@link #getSubject() JAAS subject}. + * namespace registry} but which has a different {@link #getSecurityContext() security context}. *
* * @author Randall Hauch @@ -74,13 +62,11 @@ public class ExecutionContext implements ClassLoaderFactory, Cloneable { private final ClassLoaderFactory classLoaderFactory; - private final LoginContext loginContext; - private final AccessControlContext accessControlContext; - private final Subject subject; private final PropertyFactory propertyFactory; private final ValueFactories valueFactories; private final NamespaceRegistry namespaceRegistry; private final MimeTypeDetector mimeTypeDetector; + private final SecurityContext securityContext; /** * Create an instance of an execution context that uses the {@link AccessController#getContext() current JAAS calling context} @@ -88,8 +74,10 @@ * {@link #getNamespaceRegistry() namespace registry}. */ public ExecutionContext() { - this(null, null, null, null, null, null, null); + this(new NullSecurityContext(), null, null, null, null, null); initializeDefaultNamespaces(this.getNamespaceRegistry()); + assert securityContext != null; + } /** @@ -100,9 +88,7 @@ */ protected ExecutionContext( ExecutionContext original ) { CheckArg.isNotNull(original, "original"); - this.loginContext = original.getLoginContext(); - this.accessControlContext = original.getAccessControlContext(); - this.subject = original.getSubject(); + this.securityContext = original.getSecurityContext(); this.namespaceRegistry = original.getNamespaceRegistry(); this.valueFactories = original.getValueFactories(); this.propertyFactory = original.getPropertyFactory(); @@ -114,16 +100,14 @@ * Create a copy of the supplied execution context, but use the supplied {@link AccessControlContext} instead. * * @param original the original - * @param accessControlContext the access control context + * @param securityContext the security context * @throws IllegalArgumentException if the original or access control context are is null */ protected ExecutionContext( ExecutionContext original, - AccessControlContext accessControlContext ) { + SecurityContext securityContext ) { CheckArg.isNotNull(original, "original"); - CheckArg.isNotNull(accessControlContext, "accessControlContext"); - this.loginContext = null; - this.accessControlContext = accessControlContext; - this.subject = Subject.getSubject(this.accessControlContext); + CheckArg.isNotNull(securityContext, "securityContext"); + this.securityContext = securityContext; this.namespaceRegistry = original.getNamespaceRegistry(); this.valueFactories = original.getValueFactories(); this.propertyFactory = original.getPropertyFactory(); @@ -132,33 +116,9 @@ } /** - * Create a copy of the supplied execution context, but use the supplied {@link LoginContext} instead. - * - * @param original the original - * @param loginContext the login context - * @throws IllegalArgumentException if the original or login context are is null - */ - protected ExecutionContext( ExecutionContext original, - LoginContext loginContext ) { - CheckArg.isNotNull(original, "original"); - CheckArg.isNotNull(loginContext, "loginContext"); - this.loginContext = loginContext; - this.accessControlContext = null; - this.subject = this.loginContext.getSubject(); - this.namespaceRegistry = original.getNamespaceRegistry(); - this.valueFactories = original.getValueFactories(); - this.propertyFactory = original.getPropertyFactory(); - this.classLoaderFactory = original.getClassLoaderFactory(); - this.mimeTypeDetector = original.getMimeTypeDetector(); - } - - /** * Create an instance of the execution context by supplying all parameters. * - * @param loginContext the login context, or null if the {@link #getSubject() subject} is to be retrieved from the - * {@link AccessController#getContext() current calling context}. - * @param accessControlContext the access control context, or null if a {@link LoginContext} is provided or if the - * {@link AccessController#getContext() current calling context} should be used + * @param securityContext the security context, or null if there is no associated authenticated user * @param namespaceRegistry the namespace registry implementation, or null if a thread-safe version of * {@link SimpleNamespaceRegistry} instance should be used * @param valueFactories the {@link ValueFactories} implementation, or null if a {@link StandardValueFactories} instance @@ -170,20 +130,14 @@ * @param classLoaderFactory the {@link ClassLoaderFactory} implementation, or null if a {@link StandardClassLoaderFactory} * instance should be used */ - protected ExecutionContext( LoginContext loginContext, - AccessControlContext accessControlContext, + protected ExecutionContext( SecurityContext securityContext, NamespaceRegistry namespaceRegistry, ValueFactories valueFactories, PropertyFactory propertyFactory, MimeTypeDetector mimeTypeDetector, ClassLoaderFactory classLoaderFactory ) { - this.loginContext = loginContext; - this.accessControlContext = accessControlContext; - if (loginContext == null) { - this.subject = Subject.getSubject(accessControlContext == null ? AccessController.getContext() : accessControlContext); - } else { - this.subject = loginContext.getSubject(); - } + assert securityContext != null; + this.securityContext = securityContext; this.namespaceRegistry = namespaceRegistry != null ? namespaceRegistry : new ThreadSafeNamespaceRegistry( new SimpleNamespaceRegistry()); this.valueFactories = valueFactories == null ? new StandardValueFactories(this.namespaceRegistry) : valueFactories; @@ -237,24 +191,15 @@ } /** - * Get the {@link AccessControlContext JAAS access control context} for this context. + * Get the {@link SecurityContext security context} for this context. * - * @return the access control context; may benull
+ * @return the security context; may be null
*/
- public AccessControlContext getAccessControlContext() {
- return this.accessControlContext;
+ public SecurityContext getSecurityContext() {
+ return this.securityContext;
}
/**
- * Get the {@link LoginContext JAAS login context} for this context.
- *
- * @return the login context; may be null
- */
- public LoginContext getLoginContext() {
- return this.loginContext;
- }
-
- /**
* Get the (mutable) namespace registry for this context.
*
* @return the namespace registry; never null
@@ -273,16 +218,6 @@
}
/**
- * Get the JAAS subject for which this context was created.
- *
- * @return the subject; should never be null if JAAS is used, but will be null if there is no
- * {@link #getAccessControlContext() access control context} or {@link #getLoginContext() login context}.
- */
- public Subject getSubject() {
- return this.subject;
- }
-
- /**
* Get the factories that should be used to create values for {@link Property properties}.
*
* @return the property value factory; never null
@@ -312,8 +247,8 @@
public ExecutionContext with( NamespaceRegistry namespaceRegistry ) {
// Don't supply the value factories or property factories, since they'll have to be recreated
// to reference the supplied namespace registry ...
- return new ExecutionContext(this.getLoginContext(), this.getAccessControlContext(), namespaceRegistry, null, null,
- this.getMimeTypeDetector(), this.getClassLoaderFactory());
+ return new ExecutionContext(this.getSecurityContext(), namespaceRegistry, null, null, this.getMimeTypeDetector(),
+ this.getClassLoaderFactory());
}
/**
@@ -327,8 +262,8 @@
public ExecutionContext with( MimeTypeDetector mimeTypeDetector ) {
// Don't supply the value factories or property factories, since they'll have to be recreated
// to reference the supplied namespace registry ...
- return new ExecutionContext(getLoginContext(), getAccessControlContext(), getNamespaceRegistry(), getValueFactories(),
- getPropertyFactory(), mimeTypeDetector, getClassLoaderFactory());
+ return new ExecutionContext(this.getSecurityContext(), getNamespaceRegistry(), getValueFactories(), getPropertyFactory(),
+ mimeTypeDetector, getClassLoaderFactory());
}
/**
@@ -342,135 +277,26 @@
public ExecutionContext with( ClassLoaderFactory classLoaderFactory ) {
// Don't supply the value factories or property factories, since they'll have to be recreated
// to reference the supplied namespace registry ...
- return new ExecutionContext(getLoginContext(), getAccessControlContext(), getNamespaceRegistry(), getValueFactories(),
- getPropertyFactory(), getMimeTypeDetector(), classLoaderFactory);
+ return new ExecutionContext(this.getSecurityContext(), getNamespaceRegistry(), getValueFactories(), getPropertyFactory(),
+ getMimeTypeDetector(), classLoaderFactory);
}
/**
- * Creates an {@link ExecutionContext} that is the same as this context, but which uses the supplied
- * {@link AccessControlContext access control context}.
+ * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied {@link SecurityContext
+ * security context}.
*
- * @param accessControlContext the JAAS access control context that should be used
+ * @param securityContext the new security context to use; may be null
* @return the execution context that is identical with this execution context, but with a different security context; never
* null
- * @throws IllegalArgumentException if accessControlContext
is null
.
- */
- public ExecutionContext create( AccessControlContext accessControlContext ) {
- return new ExecutionContext(this, accessControlContext);
- }
-
- /**
- * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied {@link LoginContext}. A
- * LoginContext has a variety of constructors, including contructors that take combinations of
- * {@link Configuration#getAppConfigurationEntry(String) application configuration name}, {@link Subject subject},
- * {@link CallbackHandler callback handlers}, and a {@link Configuration JAAS configuration}.
- *
- * @param loginContext the JAAS login context
- * @return the execution context that is identical with this execution context, but with a different security context; never
- * null
- * @throws IllegalArgumentException if the loginContext
is null
- */
- public ExecutionContext create( LoginContext loginContext ) {
- 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}.
- *
- * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
- * @return the execution context that is identical with this execution context, but with a different security context; never
- * null
* @throws IllegalArgumentException if the name
is null
* @throws LoginException if there name
is invalid (or there is no login context named "other"), or if the
* default callback handler JAAS property was not set or could not be loaded
*/
- public ExecutionContext with( String name ) throws LoginException {
- return new ExecutionContext(this, new LoginContext(name));
+ public ExecutionContext with( SecurityContext securityContext ) throws LoginException {
+ return new ExecutionContext(this, securityContext);
}
/**
- * 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 Subject JAAS subject}.
- *
- * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
- * @param subject the subject to authenticate
- * @return the execution context that is identical with this execution context, but with a different security context; never
- * null
- * @throws LoginException if there name
is invalid (or there is no login context named "other"), if the default
- * callback handler JAAS property was not set or could not be loaded, or if the subject
is null or
- * unknown
- */
- public ExecutionContext with( String name,
- Subject subject ) throws LoginException {
- return new ExecutionContext(this, new LoginContext(name, subject));
- }
-
- /**
- * 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} (used to handle authentication callbacks).
- *
- * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
- * @param callbackHandler the callback handler that will be used by {@link LoginModule}s to communicate with the user to
- * authenticate
- * @return the execution context that is identical with this execution context, but with a different security context; never
- * null
- * @throws LoginException if there name
is invalid (or there is no login context named "other"), or if the
- * callbackHandler
is null
- */
- public ExecutionContext with( String name,
- CallbackHandler callbackHandler ) throws LoginException {
- 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 name
is invalid (or there is no login context named "other"), or if the
- * callbackHandler
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).
- *
- * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
- * @param subject the subject to authenticate
- * @param callbackHandler the callback handler that will be used by {@link LoginModule}s to communicate with the user to
- * authenticate
- * @return the execution context that is identical with this execution context, but with a different security context; never
- * null
- * @throws LoginException if there name
is invalid (or there is no login context named "other"), if the default
- * callback handler JAAS property was not set or could not be loaded, if the subject
is null or unknown,
- * or if the callbackHandler
is null
- */
- public ExecutionContext with( String name,
- Subject subject,
- CallbackHandler callbackHandler ) throws LoginException {
- LoginContext loginContext = new LoginContext(name, subject, callbackHandler);
- loginContext.login();
-
- return new ExecutionContext(this, loginContext);
- }
-
- /**
* {@inheritDoc}
*
* @see java.lang.Object#clone()
@@ -487,7 +313,7 @@
*/
@Override
public String toString() {
- return "Execution context for " + getSubject();
+ return "Execution context for " + getSecurityContext() == null ? "null" : getSecurityContext().getUserName();
}
/**
@@ -507,106 +333,23 @@
}
/**
- * A simple {@link CallbackHandler callback handler} implementation that attempts to provide a user ID and password to any
- * callbacks that it handles.
+ * Default security context that confers no roles.
*/
- protected final class UserPasswordCallbackHandler implements CallbackHandler {
+ private static class NullSecurityContext implements SecurityContext {
- private static final boolean LOG_TO_CONSOLE = false;
+ @Override
+ public String getUserName() {
+ return null;
+ }
- private final String userId;
- private final char[] password;
-
- protected UserPasswordCallbackHandler( String userId,
- char[] password ) {
- this.userId = userId;
- this.password = password.clone();
+ @Override
+ public boolean hasRole( String roleName ) {
+ return false;
}
- /**
- * {@inheritDoc}
- *
- * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
- */
- public void handle( Callback[] callbacks ) throws UnsupportedCallbackException, IOException {
- boolean userSet = false;
- boolean passwordSet = false;
-
- 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);
- userSet = true;
-
- } 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);
- passwordSet = true;
-
- } else {
- /*
- * Jetty uses its own callback for setting the password. Since we're using Jetty for integration
- * testing of the web project(s), we have to accomodate this. Rather than introducing a direct
- * dependency, we'll add code to handle the case of unexpected callback handlers with a setObject method.
- */
- try {
- // Assume that a callback chain will ask for the user before the password
- if (!userSet) {
- new Reflection(callbacks[i].getClass()).invokeSetterMethodOnTarget("object", callbacks[i], this.userId);
- userSet = true;
- }
- else if (!passwordSet) {
- // Jetty also seems to eschew passing passwords as char arrays
- new Reflection(callbacks[i].getClass()).invokeSetterMethodOnTarget("object", callbacks[i], new String(this.password));
- passwordSet = true;
- }
- // It worked - need to continue processing the callbacks
- continue;
- } catch (Exception ex) {
- // If the property cannot be set, fall through to the failure
- }
- throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback: "
- + callbacks[i].getClass().getName());
- }
- }
-
+ @Override
+ public void logout() {
}
+
}
}
Index: dna-graph/src/main/java/org/jboss/dna/graph/JaasSecurityContext.java
===================================================================
--- dna-graph/src/main/java/org/jboss/dna/graph/JaasSecurityContext.java (revision 0)
+++ dna-graph/src/main/java/org/jboss/dna/graph/JaasSecurityContext.java (revision 0)
@@ -0,0 +1,297 @@
+package org.jboss.dna.graph;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+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;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.common.util.Reflection;
+
+/**
+ * JAAS-based {@link SecurityContext security context} that provides authentication and authorization through the JAAS
+ * {@link LoginContext login context}.
+ */
+public final class JaasSecurityContext implements SecurityContext {
+
+ private final Logger log = Logger.getLogger(getClass());
+
+ private final LoginContext loginContext;
+ private final String userName;
+ private final Setname
is null
+ * @throws LoginException if there name
is invalid (or there is no login context named "other"), or if the
+ * default callback handler JAAS property was not set or could not be loaded
+ */
+ public JaasSecurityContext( String realmName ) throws LoginException {
+ this(new LoginContext(realmName));
+ }
+
+ /**
+ * Create a {@link JaasSecurityContext} with the supplied {@link Configuration#getAppConfigurationEntry(String) application
+ * configuration name} and a {@link Subject JAAS subject}.
+ *
+ * @param realmName the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
+ * @param subject the subject to authenticate
+ * @throws LoginException if there name
is invalid (or there is no login context named "other"), if the default
+ * callback handler JAAS property was not set or could not be loaded, or if the subject
is null or
+ * unknown
+ */
+ public JaasSecurityContext( String realmName,
+ Subject subject ) throws LoginException {
+ this(new LoginContext(realmName, subject));
+ }
+
+ /**
+ * Create a {@link JaasSecurityContext} with the supplied {@link Configuration#getAppConfigurationEntry(String) application
+ * configuration name} and a {@link CallbackHandler JAAS callback handler} to create a new {@link JaasSecurityContext JAAS
+ * login context} with the given user ID and password.
+ *
+ * @param realmName 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
+ * @throws LoginException if there name
is invalid (or there is no login context named "other"), or if the
+ * callbackHandler
is null
+ */
+
+ public JaasSecurityContext( String realmName,
+ String userId,
+ char[] password ) throws LoginException {
+ this(new LoginContext(realmName, new UserPasswordCallbackHandler(userId, password)));
+ }
+
+ /**
+ * Create a {@link JaasSecurityContext} with the supplied {@link Configuration#getAppConfigurationEntry(String) application
+ * configuration name} and the given callback handler.
+ *
+ * @param realmName the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
+ * ; may not be null
+ * @param callbackHandler the callback handler to use during the login process; may not be null
+ * @throws LoginException if there name
is invalid (or there is no login context named "other"), or if the
+ * callbackHandler
is null
+ */
+
+ public JaasSecurityContext( String realmName,
+ CallbackHandler callbackHandler ) throws LoginException {
+ this(new LoginContext(realmName, callbackHandler));
+ }
+
+ /**
+ * Creates a new JAAS security context based on the given login context. If {@link LoginContext#login() login} has not already
+ * been invoked on the login context, this constructor will attempt to invoke it.
+ *
+ * @param loginContext the login context to use; may not be null
+ * @throws LoginException if the context has not already had {@link LoginContext#login() its login method} invoked and an
+ * error occurs attempting to invoke the login method.
+ * @see LoginContext
+ */
+ public JaasSecurityContext( LoginContext loginContext ) throws LoginException {
+ CheckArg.isNotNull(loginContext, "loginContext");
+ this.entitlements = new HashSet+ * A security context should only be associated with the execution context after authentication has occurred. + *
+ */ +public interface SecurityContext { + + /** + * Returns the authenticated user's name + * + * @return the authenticated user's name + */ + String getUserName(); + + /** + * Returns whether the authenticated user has the given role. + * + * @param roleName the name of the role to check + * @return true if the user has the role and is logged in; false otherwise + */ + boolean hasRole( String roleName ); + + /** + * Logs the user out of the authentication mechanism. + *+ * For some authentication mechanisms, this will be implemented as a no-op. + *
+ */ + void logout(); + +} Property changes on: dna-graph\src\main\java\org\jboss\dna\graph\SecurityContext.java ___________________________________________________________________ Added: svn:keywords + Id Revision Added: svn:eol-style + LF Index: dna-graph/src/test/java/org/jboss/dna/graph/MockSecurityContext.java =================================================================== --- dna-graph/src/test/java/org/jboss/dna/graph/MockSecurityContext.java (revision 0) +++ dna-graph/src/test/java/org/jboss/dna/graph/MockSecurityContext.java (revision 0) @@ -0,0 +1,38 @@ +package org.jboss.dna.graph; + +import java.util.Collections; +import java.util.Set; + +/** + * Mock security context for testing that grants a set of roles. + */ +public class MockSecurityContext implements SecurityContext { + + private final String userName; + private final Set- * Entitlements are exposed through this method to allow for easier mock testing. - *
+ * Returns whether the authenticated user has the given role. * - * @return the entitlements (permissions) available to the {@link ExecutionContext#getSubject() subject} for this session. + * @param roleName the name of the role to check + * @return true if the user has the role and is logged in; false otherwise */ - Set+ * This class provides a means of passing security information about an authenticated user into {@link JcrSession the DNA JCR + * session implementation} without using JAAS. This class effectively bypasses DNA's internal authentication mechanisms, so it is + * very important that this context be provided for authenticated users only. + *
+ */ +public final class SecurityContextCredentials implements Credentials { + private static final long serialVersionUID = 1L; + private final SecurityContext securityContext; + + /** + * Initializes the class with an existing {@link SecurityContext security context}. + * + * @param securityContext the security context; may not be null + */ + public SecurityContextCredentials( SecurityContext securityContext ) { + CheckArg.isNotNull(securityContext, "securityContext"); + + this.securityContext = securityContext; + } + + /** + * Returns the {@link SecurityContext security context} for this instance. + * + * @return the {@link SecurityContext security context} for this instance; never null + */ + public final SecurityContext getSecurityContext() { + return this.securityContext; + } +} Property changes on: dna-jcr\src\main\java\org\jboss\dna\jcr\SecurityContextCredentials.java ___________________________________________________________________ Added: svn:keywords + Id Revision Added: svn:eol-style + LF Index: dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties =================================================================== --- dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties (revision 982) +++ dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties (working copy) @@ -21,17 +21,17 @@ # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA, or see the FSF site: http://www.fsf.org. # -cannotConvertValue = Cannot convert {0} value to {1}. -credentialsMustProvideJaasMethod = The Credentials class "{0}" must implement either "public LoginContext getLoginContext();" or "public AccessControlContext getAccessControlContext();". -credentialsMustReturnAccessControlContext = The "getAccessControlContext()" method in Credentials class "{0}" must not return a null. -credentialsMustReturnLoginContext = The "getLoginContext()" method in Credentials class "{0}" must not return a null. +cannotConvertValue = Cannot convert {0} value to {1} +credentialsMustProvideJaasMethod = The Credentials class "{0}" must implement "public LoginContext getLoginContext();", be an instance of "javax.jcr.SimpleCredentials", or be an instance of "org.jboss.dna.jcr.SecurityContextCredentials" +mustBeInPrivilegedAction=login() can only be called successfully from within a java.security.PrivilegedAction +credentialsMustReturnLoginContext = The "getLoginContext()" method in Credentials class "{0}" must not return a null defaultWorkspaceName= -inputStreamConsumed = This value was already consumed as an input stream. -nonInputStreamConsumed = This value was already consumed as a non-input stream. +inputStreamConsumed = This value was already consumed as an input stream +nonInputStreamConsumed = This value was already consumed as a non-input stream pathNotFound = No item exists at path {0} in workspace "{1}" pathNotFoundRelativeTo = No item exists at path {0} relative to {1} in workspace "{2}" -permissionDenied = Permission denied to perform actions "{1}" on path {0}. -repositoryMustBeConfigured = DNA repositories must be configured with either a repository source factory or a repository source. +permissionDenied = Permission denied to perform actions "{1}" on path {0} +repositoryMustBeConfigured = DNA repositories must be configured with either a repository source factory or a repository source sourceInUse = All sessions must end before a new repository source can be set repositoryDoesNotExist = There is no repository named "{0}" fileDoesNotExist = Unable to find or read the file "{0}" Index: dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java (revision 982) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java (working copy) @@ -32,6 +32,7 @@ import org.jboss.dna.common.statistic.Stopwatch; import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.Graph; +import org.jboss.dna.graph.MockSecurityContext; import org.jboss.dna.graph.connector.RepositoryConnection; import org.jboss.dna.graph.connector.RepositoryConnectionFactory; import org.jboss.dna.graph.connector.RepositorySourceException; @@ -89,7 +90,7 @@ repository = new JcrRepository(context, connectionFactory, "unused"); - session = (JcrSession) repository.login(); + session = (JcrSession) repository.login(new SecurityContextCredentials(new MockSecurityContext(null))); } @After Index: dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java (revision 982) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java (working copy) @@ -31,6 +31,7 @@ import javax.jcr.Node; import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.Graph; +import org.jboss.dna.graph.MockSecurityContext; import org.jboss.dna.graph.connector.RepositoryConnection; import org.jboss.dna.graph.connector.RepositoryConnectionFactory; import org.jboss.dna.graph.connector.RepositorySourceException; @@ -97,7 +98,7 @@ repository = new JcrRepository(context, connectionFactory, "unused"); - session = (JcrSession) repository.login(); + session = (JcrSession) repository.login(new SecurityContextCredentials(new MockSecurityContext(null))); } @After Index: dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java (revision 982) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java (working copy) @@ -29,24 +29,29 @@ import static org.junit.Assert.assertThat; import java.security.AccessControlContext; import java.security.AccessController; +import java.security.PrivilegedExceptionAction; import java.util.HashMap; import java.util.Map; import javax.jcr.Credentials; import javax.jcr.Repository; import javax.jcr.Session; +import javax.jcr.SimpleCredentials; +import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.Graph; +import org.jboss.dna.graph.MockSecurityContext; +import org.jboss.dna.graph.JaasSecurityContext.UserPasswordCallbackHandler; import org.jboss.dna.graph.connector.RepositoryConnection; import org.jboss.dna.graph.connector.RepositoryConnectionFactory; import org.jboss.dna.graph.connector.RepositorySourceException; import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource; +import org.jboss.security.config.IDTrustConfiguration; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.mockito.MockitoAnnotations.Mock; /** * @author jverhaeg @@ -59,19 +64,23 @@ private InMemoryRepositorySource source; private Map