User: stark
Date: 01/02/14 13:20:08
Added: security/src/main/org/jboss/security
AbstractSecurityProxy.java SecurityProxy.java
SecurityProxyFactory.java SubjectSecurityProxy.java
SubjectSecurityProxyFactory.java
Log:
Updated SecurityInterceptor to be independent of any JAAS classes
and refactored security proxy layer to simplify the model.
Revision Changes Path
1.1
contrib/security/src/main/org/jboss/security/AbstractSecurityProxy.java
Index: AbstractSecurityProxy.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import javax.ejb.EJBContext;
import org.jboss.ejb.MethodInvocation;
import org.jboss.test.security.test.ejbs.project.ProjRepositorySecurityProxy2;
/** An abstract implementation of SecurityProxy that wraps a non-SecurityProxy
object. Subclasses of this class are used to create a SecurityProxy given
a security delegate that implements methods in the EJB home or remote
interface for security checks. This allows custom security classes to be
written without using a JBoss specific interface. It also allows the security
delegate to follow a natural proxy pattern implementation.
@author [EMAIL PROTECTED]
@version $Revision: 1.1 $
*/
public abstract class AbstractSecurityProxy implements SecurityProxy
{
private HashMap methodMap;
private Method setContextMethod;
private Method setBeanMethod;
protected Object delegate;
AbstractSecurityProxy(Object delegate)
{
this.delegate = delegate;
methodMap = new HashMap();
}
/** Subclasses implement this method to actually invoke the given home
method on the proxy delegate.
@param m, the delegate method that was mapped from the ejb home method.
@param args, the method invocation arguments.
@param delegate, the proxy delegate object associated with the
AbstractSecurityProxy
@see invokeHome(Method, Object[])
*/
protected abstract void invokeHomeOnDelegate(Method m, Object[] args, Object
delegate) throws SecurityException;
/** Subclasses implement this method to actually invoke the given remote
method on the proxy delegate.
@param m, the delegate method that was mapped from the ejb remote method.
@param args, the method invocation arguments.
@param delegate, the proxy delegate object associated with the
AbstractSecurityProxy
@see invoke(Method, Object[], Object)
*/
protected abstract void invokeOnDelegate(Method m, Object[] args, Object
delegate) throws SecurityException;
/** This method is called by the container SecurityInterceptor to intialize
the proxy with the EJB home and remote interface classes that the
container is housing. This method creates a mapping from the home and
remote classes to the proxy delegate instance. The mapping is based on
method name and paramter types. In addition, the proxy delegate is
inspected for a setEJBContext(EJBContext) and a setBean(Object) method
so that the active EJBContext and EJB instance can be passed to the
delegate prior to method invocations.
@param beanHome, the class for the EJB home interface
@param beanRemote, the class for the EJB remote interface
@param securityMgr, The security manager instance assigned to the container.
It is not used by this class.
*/
public void init(Class beanHome, Class beanRemote, Object securityMgr) throws
InstantiationException
{
mapHomeMethods(beanHome);
mapRemoteMethods(beanRemote);
try
{
Class[] parameterTypes = {EJBContext.class};
setContextMethod = delegate.getClass().getMethod("setEJBContext",
parameterTypes);
}
catch(Exception e)
{
}
try
{
Class[] parameterTypes = {Object.class};
setBeanMethod = delegate.getClass().getMethod("setBean", parameterTypes);
}
catch(Exception e)
{
}
}
/**
*/
public void setEJBContext(EJBContext ctx)
{
if( setContextMethod != null )
{
Object[] args = {ctx};
try
{
setContextMethod.invoke(delegate, args);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
/** Called by the SecurityInterceptor to allow the proxy delegate to perform
a security check of the indicated home interface method.
@param m, the EJB home interface method
@param args, the method arguments
*/
public void invokeHome(final Method m, Object[] args) throws SecurityException
{
Method delegateMethod = (Method) methodMap.get(m);
if( delegateMethod != null )
invokeHomeOnDelegate(delegateMethod, args, delegate);
}
/** Called by the SecurityInterceptor to allow the proxy delegate to perform
a security check of the indicated remote interface method.
@param m, the EJB remote interface method
@param args, the method arguments
@param bean, the EJB bean instance
*/
public void invoke(final Method m, final Object[] args, final Object bean)
throws SecurityException
{ // Get authenticated subject and invoke invokeAsSubject in
Subject.doAsPrivaledged() block...
Method delegateMethod = (Method) methodMap.get(m);
System.out.println("invoke("+m+") -> delegateMethod="+delegateMethod);
if( delegateMethod != null )
{
if( setBeanMethod != null )
{
Object[] bargs = {bean};
try
{
setBeanMethod.invoke(delegate, bargs);
}
catch(Exception e)
{
e.printStackTrace();
throw new SecurityException("Failed to set bean on
proxy"+e.getMessage());
}
}
invokeOnDelegate(delegateMethod, args, delegate);
}
}
/** Performs a mapping from the methods declared in the beanHome
class to the proxy delegate class.
*/
protected void mapHomeMethods(Class beanHome)
{
Class delegateClass = delegate.getClass();
Method[] methods = beanHome.getMethods();
for(int m = 0; m < methods.length; m ++)
{
// Check for ejbCreate... methods
Method hm = methods[m];
Class[] parameterTypes = hm.getParameterTypes();
String name = hm.getName();
name = "ejb" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
System.out.println("mapHomeMethods, m="+hm);
try
{
Method match = delegateClass.getMethod(name, parameterTypes);
System.out.println("..match="+match);
methodMap.put(hm, match);
}
catch(NoSuchMethodException e)
{
System.out.println("..Not found");
}
}
}
/** Performs a mapping from the methods declared in the beanRemote
class to the proxy delegate class.
*/
protected void mapRemoteMethods(Class beanRemote)
{
Class delegateClass = delegate.getClass();
Method[] methods = beanRemote.getMethods();
for(int m = 0; m < methods.length; m ++)
{
// Check for ejbCreate... methods
Method rm = methods[m];
Class[] parameterTypes = rm.getParameterTypes();
String name = rm.getName();
System.out.println("mapRemoteMethods, m="+rm);
try
{
Method match = delegateClass.getMethod(name, parameterTypes);
System.out.println("..match="+match);
methodMap.put(rm, match);
}
catch(NoSuchMethodException e)
{
System.out.println("..Not found");
}
}
}
}
1.1 contrib/security/src/main/org/jboss/security/SecurityProxy.java
Index: SecurityProxy.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
import java.lang.reflect.Method;
import javax.ejb.EJBContext;
/** An interface describing the requirements for a SecurityInterceptor proxy.
A SecurityProxy allows for the externalization of custom security checks
on a per-method basis for both the EJB home and remote interface methods.
Custom security checks are those that cannot be described using the
standard EJB deployment time declarative role based security.
@author [EMAIL PROTECTED]
@version $Revision: 1.1 $
* @stereotype plug-in point
*/
public interface SecurityProxy
{
public void init(Class beanHome, Class beanRemote, Object securityMgr) throws
InstantiationException;
/** Called prior to any invoke to set the current EJB context.
*/
public void setEJBContext(EJBContext ctx);
/** Called to allow the security proxy to perform any custom security
checks required for the EJB home interface method.
@param m, the EJB home interface method? Or is this the EJB bean impl method?
*/
public void invokeHome(Method m, Object[] args) throws SecurityException;
/** Called to allow the security proxy to perform any custom security
checks required for the EJB remote interface method.
@param m, the EJB remote interface method? Or is this the EJB bean impl method?
@param bean, the EJB implementation class instance
*/
public void invoke(Method m, Object[] args, Object bean) throws
SecurityException;
}
1.1
contrib/security/src/main/org/jboss/security/SecurityProxyFactory.java
Index: SecurityProxyFactory.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
/** An interface for factories of SecurityProxy objects. It is used
to create a SecurityProxy from a security delegate object that is
not a SecurityProxy instance.
@author [EMAIL PROTECTED]
@version $Revision: 1.1 $
*/
public interface SecurityProxyFactory
{
public SecurityProxy create(Object proxyDelegate);
}
1.1
contrib/security/src/main/org/jboss/security/SubjectSecurityProxy.java
Index: SubjectSecurityProxy.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.lang.reflect.Method;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import javax.ejb.EJBContext;
import javax.security.auth.Subject;
import org.jboss.ejb.MethodInvocation;
import org.jboss.security.SecurityPolicy;
import org.jboss.security.SubjectSecurityManager;
/** A subclass of AbstractSecurityProxy that executes as the currently
authenticated subject within the invokeHomeOnDelegate and invokeOnDelegate
methods. The current subject is accessed via the security manager passed
to the init() method, which must be an instance of SubjectSecurityManager.
This results in AccessController.checkPermission() calls made from within the
security delegate methods to be based on the Subject's permissions.
@see javax.security.auth.Policy
@see javax.security.auth.Subject
@see org.jboss.security.SecurityPolicy
@see org.jboss.security.SubjectSecurityManager
@author [EMAIL PROTECTED]
@version $Revision: 1.1 $
*/
public class SubjectSecurityProxy extends AbstractSecurityProxy
{
private SubjectSecurityManager subjectSecurityManager;
SubjectSecurityProxy(Object delegate)
{
super(delegate);
}
public void init(Class beanHome, Class beanRemote, Object securityMgr) throws
InstantiationException
{
if( (securityMgr instanceof SubjectSecurityManager) == false )
throw new InstantiationException("SubjectSecurityProxy requires a
SubjectSecurityManager instance, securityMgr="+securityMgr);
subjectSecurityManager = (SubjectSecurityManager) securityMgr;
super.init(beanHome, beanRemote, securityMgr);
}
protected void invokeHomeOnDelegate(final Method m, final Object[] args, final
Object delegate) throws SecurityException
{ // Get authenticated subject and invoke invokeAsSubject in
Subject.doAsPrivaledged() block...
final Subject subject = subjectSecurityManager.getActiveSubject();
System.out.println("SecurityInterceptor.invokeHome("+m+"), s="+subject);
if( subject == null )
throw new SecurityException("No subject associated with secure proxy");
try
{
String domainName = subjectSecurityManager.getSecurityDomain();
SecurityPolicy.setActiveApp(domainName);
Subject.doAsPrivileged(subject, new PrivilegedExceptionAction()
{
public Object run() throws Exception
{
m.invoke(delegate, args);
return null;
}
},
null
);
}
catch(PrivilegedActionException e)
{
Throwable t = e.getException();
if( t instanceof InvocationTargetException )
{
t = ((InvocationTargetException) t).getTargetException();
}
else if( t instanceof UndeclaredThrowableException )
{
t = ((UndeclaredThrowableException) t).getUndeclaredThrowable();
}
if( t instanceof SecurityException )
throw (SecurityException) t;
t.printStackTrace();
throw new SecurityException("Unexpected error during security proxy
execution:"+t.getMessage());
}
}
protected void invokeOnDelegate(final Method m, final Object[] args, final
Object delegate) throws SecurityException
{ // Get authenticated subject and invoke invokeAsSubject in
Subject.doAsPrivaledged() block...
final Subject subject = subjectSecurityManager.getActiveSubject();
System.out.println("SecurityInterceptor.invoke("+m+"), s="+subject);
if( subject == null )
throw new SecurityException("No subject associated with secure proxy");
try
{
String domainName = subjectSecurityManager.getSecurityDomain();
SecurityPolicy.setActiveApp(domainName);
Subject.doAsPrivileged(subject, new PrivilegedExceptionAction()
{
public Object run() throws Exception
{
m.invoke(delegate, args);
return null;
}
},
null
);
}
catch(PrivilegedActionException e)
{
Throwable t = e.getException();
if( t instanceof InvocationTargetException )
{
t = ((InvocationTargetException) t).getTargetException();
}
else if( t instanceof UndeclaredThrowableException )
{
t = ((UndeclaredThrowableException) t).getUndeclaredThrowable();
}
if( t instanceof SecurityException )
throw (SecurityException) t;
t.printStackTrace();
throw new SecurityException("Unexpected error during security proxy
execution:"+t.getMessage());
}
}
}
1.1
contrib/security/src/main/org/jboss/security/SubjectSecurityProxyFactory.java
Index: SubjectSecurityProxyFactory.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.security;
import java.io.Serializable;
/** An implementation of SecurityProxyFactory that creates SubjectSecurityProxy
objects to wrap the raw security proxy objects.
@author [EMAIL PROTECTED]
@version $Revision: 1.1 $
*/
public class SubjectSecurityProxyFactory implements SecurityProxyFactory,
Serializable
{
public SecurityProxy create(Object proxyDelegate)
{
SecurityProxy proxy = new SubjectSecurityProxy(proxyDelegate);
return proxy;
}
}