Author: dblevins
Date: Thu Sep 27 18:48:35 2007
New Revision: 580192
URL: http://svn.apache.org/viewvc?rev=580192&view=rev
Log:
Added SecurityService.disassociate and SecurityService.logout and revised
associate
Added generics to the SecurityService interface.
Revised the usage in the TomcatSecurityService
Added:
openejb/trunk/openejb3/assembly/openejb-standalone/README.html
Modified:
openejb/trunk/openejb3/assembly/openejb-tomcat/src/main/java/org/apache/openejb/tomcat/TomcatSecurityService.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicPolicyConfiguration.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java
openejb/trunk/openejb3/container/openejb-jee/src/test/java/org/apache/openejb/jee/JeeTest.java
openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
Added: openejb/trunk/openejb3/assembly/openejb-standalone/README.html
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-standalone/README.html?rev=580192&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-standalone/README.html (added)
+++ openejb/trunk/openejb3/assembly/openejb-standalone/README.html Thu Sep 27
18:48:35 2007
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD><TITLE>Apache OpenEJB 6.0.14</TITLE>
+<META http-equiv=Content-Type content="text/html">
+</HEAD>
+<BODY>
+<P>
+<H3>Apache OpenEJB 3.0-beta-1</H3>
+<P></P>
+<p><font color="red">OpenEJB 3.0-beta-1 requires JRE 5.0 (not compatible with
JRE 6.0). Read the <a href="RELEASE-NOTES.txt">RELEASE-NOTES</a> for more
details.</font></p>
+
+<p>Packaging Details (or "What Should I Download?")
+ <ul>
+ <li>
+ OpenEJB Standlone Server:
+ <ul>
+ <li><a
href="openejb-3.0-beta-1-bin.zip">openejb-3.0-beta-1-bin.zip</a></li>
+ <li><a
href="openejb-3.0-beta-1-bin.tar.gz">openejb-3.0-beta-1-bin.tar.gz</a></li>
+ </ul>
+ </li>
+ <li>
+ OpenEJB for Tomcat (deploy into a Tomcat 6.x server):
+ <ul>
+ <li><a href="openejb.war">openejb.war</a></li>
+ </ul>
+ </li>
+ <li>
+ EJB 3.0 and other examples:
+ <ul>
+ <li><a
href="examples-3.0-beta-1.zip">examples-3.0-beta-1.zip</a></li>
+ <li><a
href="examples-3.0-beta-1.tar.gz">examples-3.0-beta-1.tar.gz</a></li>
+ </ul>
+ </li>
+ <li>
+ Source:
+ <ul>
+ <li><a
href="openejb-3.0-beta-1-src.zip">openejb-3.0-beta-1-src.zip</a></li>
+ <li><a
href="openejb-3.0-beta-1-src.tar.gz">openejb-3.0-beta-1-src.tar.gz</a></li>
+ </ul>
+ </li>
+ </ul>
+</p>
+
+<P>Thank you for using <A href="http://openejb.apache.org/">OpenEJB</A>!.
+</P>
+<P><B>The Apache OpenEJB Project</B> <BR><A
+href="http://openejb.apache.org/">http://openejb.apache.org/</A> </P>
+<P>
+<P></P></BODY></HTML>
Modified:
openejb/trunk/openejb3/assembly/openejb-tomcat/src/main/java/org/apache/openejb/tomcat/TomcatSecurityService.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/src/main/java/org/apache/openejb/tomcat/TomcatSecurityService.java?rev=580192&r1=580191&r2=580192&view=diff
==============================================================================
---
openejb/trunk/openejb3/assembly/openejb-tomcat/src/main/java/org/apache/openejb/tomcat/TomcatSecurityService.java
(original)
+++
openejb/trunk/openejb3/assembly/openejb-tomcat/src/main/java/org/apache/openejb/tomcat/TomcatSecurityService.java
Thu Sep 27 18:48:35 2007
@@ -32,6 +32,7 @@
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.LinkedList;
+import java.util.UUID;
public class TomcatSecurityService extends AbstractSecurityService {
static protected final ThreadLocal<LinkedList<Subject>> runAsStack = new
ThreadLocal<LinkedList<Subject>>() {
@@ -55,14 +56,14 @@
}
}
- public Object login(String realmName, String username, String password)
throws LoginException {
+ public UUID login(String realmName, String username, String password)
throws LoginException {
if (defaultRealm == null) {
throw new LoginException("No Tomcat realm available");
}
Principal principal = defaultRealm.authenticate(username, password);
Subject subject = createSubject(defaultRealm, principal);
- Object token = registerSubject(subject);
+ UUID token = registerSubject(subject);
return token;
}
@@ -99,13 +100,20 @@
}
public Object enterWebApp(Realm realm, Principal principal, String runAs) {
- Subject newSubject = null;
+ UUID newToken = null;
if (principal != null) {
- newSubject = createSubject(realm, principal);
+ Subject newSubject = createSubject(realm, principal);
+ newToken = registerSubject(newSubject);
+ }
+
+ UUID oldToken = disassociate();
+ WebAppState webAppState = new WebAppState(oldToken, runAs != null);
+ try {
+ associate(newToken);
+ } catch (LoginException e) {
+ throw new IllegalStateException("Subject was registered, but
cannot be associated with the SecurityService", e);
}
- WebAppState webAppState = new WebAppState(clientIdentity.get(), runAs
!= null);
- clientIdentity.set(newSubject);
if (runAs != null) {
Subject runAsSubject = createRunAsSubject(runAs);
@@ -118,7 +126,12 @@
public void exitWebApp(Object state) {
if (state instanceof WebAppState) {
WebAppState webAppState = (WebAppState) state;
- clientIdentity.set(webAppState.oldSubject);
+ disassociate();
+ try {
+ if (webAppState.oldToken != null)
associate(webAppState.oldToken);
+ } catch (LoginException e) {
+ throw new IllegalStateException("Subject was registered, but
cannot be associated with the SecurityService", e);
+ }
if (webAppState.hadRunAs) {
runAsStack.get().removeFirst();
}
@@ -224,12 +237,12 @@
}
private static class WebAppState {
- private final Subject oldSubject;
+ private final UUID oldToken;
private final boolean hadRunAs;
- public WebAppState(Subject oldSubject, boolean hadRunAs) {
- this.oldSubject = oldSubject;
+ public WebAppState(UUID oldSubject, boolean hadRunAs) {
+ this.oldToken = oldSubject;
this.hadRunAs = hadRunAs;
}
}
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java?rev=580192&r1=580191&r2=580192&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
Thu Sep 27 18:48:35 2007
@@ -22,7 +22,9 @@
import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.core.CoreDeploymentInfo;
import org.apache.openejb.core.security.jacc.BasicJaccProvider;
+import org.apache.openejb.core.security.jacc.BasicPolicyConfiguration;
import org.apache.openejb.InterfaceType;
+import org.apache.openejb.loader.SystemInstance;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
@@ -47,12 +49,16 @@
import java.util.Map;
import java.util.LinkedHashSet;
import java.util.concurrent.ConcurrentHashMap;
-import java.io.Serializable;
import java.lang.reflect.Method;
-public abstract class AbstractSecurityService implements SecurityService,
ThreadContextListener {
+/**
+ * This security service chooses a UUID as its token as this can be serialized
+ * to clients, is mostly secure, and can be deserialized in a client vm without
+ * addition openejb-core classes.
+ */
+public abstract class AbstractSecurityService implements
SecurityService<UUID>, ThreadContextListener,
BasicPolicyConfiguration.RoleResolver {
static private final Map<Object, Identity> identities = new
ConcurrentHashMap<Object, Identity>();
- static protected final ThreadLocal<Subject> clientIdentity = new
ThreadLocal<Subject>();
+ static private final ThreadLocal<Identity> clientIdentity = new
ThreadLocal<Identity>();
protected final String defaultUser = "guest";
protected final Subject defaultSubject;
protected final SecurityContext defaultContext;
@@ -67,6 +73,8 @@
defaultSubject = createSubject(defaultUser);
defaultContext = new SecurityContext(defaultSubject);
+
+
SystemInstance.get().setComponent(BasicPolicyConfiguration.RoleResolver.class,
this);
}
@@ -81,7 +89,7 @@
public void init(Properties props) throws Exception {
}
- public Object login(String username, String password) throws
LoginException {
+ public UUID login(String username, String password) throws LoginException {
return login(realmName, username, password);
}
@@ -110,10 +118,9 @@
} else if (securityContext == null) {
- Subject subject = clientIdentity.get();
-
- if (subject != null){
- securityContext = new SecurityContext(subject);
+ Identity identity = clientIdentity.get();
+ if (identity != null){
+ securityContext = new SecurityContext(identity.subject);
} else {
securityContext = defaultContext;
}
@@ -142,39 +149,41 @@
}
}
- protected Object registerSubject(Subject subject) {
+ protected UUID registerSubject(Subject subject) {
Identity identity = new Identity(subject);
- Serializable token = identity.getToken();
+ UUID token = identity.getToken();
identities.put(token, identity);
return token;
}
- protected void unregisterSubject(Object securityIdentity) {
+ public void logout(UUID securityIdentity) throws LoginException {
+ Identity identity = identities.get(securityIdentity);
+ if (identity == null) throw new LoginException("Identity is not
currently logged in: " + securityIdentity);
identities.remove(securityIdentity);
}
- public Object associate(Object securityIdentity) throws LoginException {
- Object oldIdentity = new SubjectHolder(clientIdentity.get());
-
- Subject subject = null;
- if (securityIdentity != null) {
+ protected void unregisterSubject(Object securityIdentity) {
+ identities.remove(securityIdentity);
+ }
- Identity identity = identities.get(securityIdentity);
- if (identity == null) throw new LoginException("Identity does not
exist: " + securityIdentity);
+ public void associate(UUID securityIdentity) throws LoginException {
+ if (clientIdentity.get() != null) throw new LoginException("Thread
already associated with a client identity. Refusing to overwrite.");
+ if (securityIdentity == null) throw new NullPointerException("The
security token passed in is null");
- subject = identity.subject;
- }
- clientIdentity.set(subject);
+ // The securityIdentity token must associated with a logged in Identity
+ Identity identity = identities.get(securityIdentity);
+ if (identity == null) throw new LoginException("Identity is not
currently logged in: " + securityIdentity);
- return oldIdentity;
+ clientIdentity.set(identity);
}
- public void disassociate(Object oldIdentity) {
- if (!(oldIdentity instanceof SubjectHolder)) {
- throw new IllegalArgumentException("oldIdentity is not an object
returned from associate");
+ public UUID disassociate() {
+ try {
+ Identity identity = clientIdentity.get();
+ return (identity == null)? null: identity.getToken();
+ } finally {
+ clientIdentity.remove();
}
- SubjectHolder subjectHolder = (SubjectHolder) oldIdentity;
- clientIdentity.set(subjectHolder.subject);
}
public boolean isCallerInRole(String role) {
@@ -287,7 +296,7 @@
return subject;
}
- public Serializable getToken() {
+ public UUID getToken() {
return token;
}
}
@@ -330,14 +339,6 @@
public String getName() {
return name;
- }
- }
-
- private static class SubjectHolder {
- private final Subject subject;
-
- public SubjectHolder(Subject subject) {
- this.subject = subject;
}
}
}
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java?rev=580192&r1=580191&r2=580192&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/SecurityServiceImpl.java
Thu Sep 27 18:48:35 2007
@@ -23,6 +23,7 @@
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.net.URL;
+import java.util.UUID;
/**
* @version $Rev$ $Date$
@@ -54,7 +55,7 @@
System.setProperty("java.security.auth.login.config",
loginConfig.toExternalForm());
}
- public Object login(String realmName, String username, String password)
throws LoginException {
+ public UUID login(String realmName, String username, String password)
throws LoginException {
if (realmName == null){
realmName = getRealmName();
}
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicPolicyConfiguration.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicPolicyConfiguration.java?rev=580192&r1=580191&r2=580192&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicPolicyConfiguration.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicPolicyConfiguration.java
Thu Sep 27 18:48:35 2007
@@ -63,8 +63,8 @@
Principal[] principals = domain.getPrincipals();
if (principals.length == 0) return false;
- SecurityService securityService =
SystemInstance.get().getComponent(SecurityService.class);
- Set<String> roles = securityService.getLogicalRoles(principals,
rolePermissionsMap.keySet());
+ RoleResolver roleResolver =
SystemInstance.get().getComponent(RoleResolver.class);
+ Set<String> roles = roleResolver.getLogicalRoles(principals,
rolePermissionsMap.keySet());
for (String role : roles) {
Permissions permissions = rolePermissionsMap.get(role);
@@ -180,5 +180,9 @@
int getState() {
return state;
+ }
+
+ public interface RoleResolver {
+ public Set<String> getLogicalRoles(Principal[] principals, Set<String>
logicalRoles);
}
}
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java?rev=580192&r1=580191&r2=580192&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java
Thu Sep 27 18:48:35 2007
@@ -49,8 +49,14 @@
return Collections.emptySet();
}
- public Object associate(Object securityIdentity) throws LoginException {
+ public void associate(Object securityIdentity) throws LoginException {
+ }
+
+ public Object disassociate() {
return null;
+ }
+
+ public void logout(Object securityIdentity) throws LoginException {
}
public boolean isCallerInRole(String role) {
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java?rev=580192&r1=580191&r2=580192&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java
Thu Sep 27 18:48:35 2007
@@ -18,32 +18,41 @@
import org.apache.openejb.InterfaceType;
-import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import java.lang.reflect.Method;
import java.security.Principal;
-import java.util.Collection;
-import java.util.Set;
-public interface SecurityService extends Service {
+/**
+ * The generic value T is any serializable token of the SecurityService
+ * implementations choosing. This token only needs to be understandable
+ * by the SecurityService internally and need not be a publicly usable class
+ * type. No part of the outlying system will make any assumptions as to the
+ * type of the object. The use of a java generic type is to express the
+ * required symmetry in the interface.
+ *
+ */
+public interface SecurityService<T> extends Service {
/**
- * Active
+ *
*/
- public Object login(String user, String pass) throws LoginException;
- public Object login(String securityRealm, String user, String pass) throws
LoginException;
+ public T login(String user, String pass) throws LoginException;
+
+ public T login(String securityRealm, String user, String pass) throws
LoginException;
+ /**
+ * Active
+ */
+ public void associate(T securityIdentity) throws LoginException;
- public Set<String> getLogicalRoles(Principal[] principals, Set<String>
logicalRoles);
-
/**
* Active
*/
- public Object associate(Object securityIdentity) throws LoginException;
+ public T disassociate();
/**
* Active
*/
-// public Object logout(Object securityIdentity) throws LoginException;
+ public void logout(T securityIdentity) throws LoginException;
/**
* Active
Modified:
openejb/trunk/openejb3/container/openejb-jee/src/test/java/org/apache/openejb/jee/JeeTest.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-jee/src/test/java/org/apache/openejb/jee/JeeTest.java?rev=580192&r1=580191&r2=580192&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-jee/src/test/java/org/apache/openejb/jee/JeeTest.java
(original)
+++
openejb/trunk/openejb3/container/openejb-jee/src/test/java/org/apache/openejb/jee/JeeTest.java
Thu Sep 27 18:48:35 2007
@@ -18,6 +18,7 @@
package org.apache.openejb.jee;
import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
@@ -30,6 +31,8 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.FileOutputStream;
+import java.io.File;
/**
* @version $Revision$ $Date$
@@ -78,9 +81,27 @@
ByteArrayOutputStream baos = new ByteArrayOutputStream();
marshaller.marshal(object, baos);
- String actual = new String(baos.toByteArray());
+ byte[] bytes = baos.toByteArray();
+ String actual = new String(bytes);
- assertEquals(expected, actual);
+ try {
+ assertEquals(expected, actual);
+ } catch (AssertionFailedError e) {
+ writeToTmpFile(bytes, xmlFileName);
+ throw e;
+ }
+ }
+
+ private void writeToTmpFile(byte[] bytes, String xmlFileName) {
+ try {
+ File tempFile = File.createTempFile("jaxb-output", "xml");
+ FileOutputStream out = new FileOutputStream(tempFile);
+ out.write(bytes);
+ out.close();
+ System.out.println("Jaxb output of "+xmlFileName+" written to
"+tempFile.getAbsolutePath());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
private java.lang.String readContent(InputStream in) throws IOException {
Modified:
openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java?rev=580192&r1=580191&r2=580192&view=diff
==============================================================================
---
openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
(original)
+++
openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
Thu Sep 27 18:48:35 2007
@@ -105,9 +105,10 @@
return;
}
+ SecurityService securityService =
SystemInstance.get().getComponent(SecurityService.class);
try {
- SecurityService securityService =
SystemInstance.get().getComponent(SecurityService.class);
- securityService.associate(req.getClientIdentity());
+ Object clientIdentity = req.getClientIdentity();
+ if (clientIdentity != null)
securityService.associate(clientIdentity);
} catch (Throwable t) {
replyWithFatalError(out, t, "Security system failed to associate
thread with the thread");
return;
@@ -197,6 +198,7 @@
} catch (java.io.IOException ie) {
logger.fatal("Couldn't write EjbResponse to output stream",
ie);
}
+ securityService.disassociate();
call.reset();
EJBHomeProxyHandle.resolver.set(null);
EJBObjectProxyHandle.resolver.set(null);