diff --git a/src/docbkx/springsecurity.xml b/src/docbkx/springsecurity.xml index 004546a61c..85cb154806 100644 --- a/src/docbkx/springsecurity.xml +++ b/src/docbkx/springsecurity.xml @@ -4485,376 +4485,6 @@ $CATALINA_HOME/bin/startup.sh Finally, restart Tomcat. - - - Context propagation support for EJBs - -
- Rationale - - Spring Security does provide transparent propagation of security - context information in specific remoting scenarios. That means that - the security context of the invoker is passed along with each method - invocation to the server. There the context is being reestablished so - that a service method can take place in the security context of the - invoker. There is out-of-the-box support for RMI or Spring's own - HttpInvoker protocol. Now many applications around are based on EJB - remoting because of requirements or policy, which are precluded from - that benefit. - - If you have an EJB application you have two options for - integrating Spring Security: - - - - Use a container adapter for integrating with that - application server's proprietary security mechanism (Spring - Security provides some ready usable adapters for use in legacy - scenarios) - - - - Create wrappers on the client side (and on the server side - when using POJO delegation) to propagate the security - context - - - - Both approaches have the benefit that the implementation of your - service, as well as its clients, are agnostic to remoting and security - context propagation taking place. The drawback of the first approach - is, that you have to reimplement parts of your security infrastructure - when switching the container (or maybe upgrading it, as sometimes the - security strategy changes over time). That issue does not arise in the - second approach, but the problem here is the implementation overhead - of creating according wrappers to hide the context propagation. - - The following chapters describe the infrastructure classes which - wrap the context propagation and abstract it away from both client - usage and service implementation. -
- -
- How it works - - See figure 1 which describes the recommended POJO delegation - model, where an EJB session bean only serves as remoting wrapper. The - actual service implementation resides inside a POJO that implements - the given business interface. The EJB implementation does nothing more - than just delegating invocations of service operations to the POJO. - Using Spring's support classes for wiring the POJO to the EJB is - simple. Spring also allows wiring the service interface to the client - by transparently wrapping the remote interface. - -
- Figure 1: Using EJB as remoting wrapper - - - - - - -
- - This concept is now slightly enhanced by the context propagation - module. As it is not possible to intercept the invocation of a remote - interface in a portable manner, we have to extend the remote interface - methods to include an additional parameter that holdes the - SecurityContext we wish to propagate. In consequence we also have to - modify the method implementations in the EJB implementation class to - take that additional argument. This is depicted in figure 2. Note - however, that the client still works with the plain business interface - we had before and that the actual service implementation class is - still the same. - -
- Figure 2: Using EJB as enhanced remoting wrapper - - - - - - -
- - Now how does this work? On the client side a proxy translates - invocations from the business interface (Service) to invocations of - the extended business interface (XService) which is actually exposed - by the remote interface. The current security context is extracted and - passed into the additionally provided method parameter. - - On the server side the EJB implementation refers to a delegate - which also exposes the extended service interface (XService). Behind - that service interface hides a proxy which extracts the passed-in - SecurityContext and establishes it in the current thread. Then it - delegates the invocation to the actual delegate class (ServiceImpl), - translating the method invocation as the target does not know about - the SecurityContext parameter. The invocation chain is exemplified in - figure 3. - -
- Figure 3: Invocation chain - - - - - - -
The yellow colored elements indicate instances exposing the - extended business interface while the green colored elements indicate - instances exposing the real business interface.
-
- -
- How to use it - - The following subsections show how to use the provided - infrastructure classes and how to enable your code to use them. - -
- The building blocks - -
- The business interface - - public interface Service { - - Result operation(Parameter param); - }How the business interface looks like depends just on, - well, your business requirements. Nothing special about it. -
- -
- The service implementation - - public class ServiceImpl implements Service { - - public Result operation(Parameter param) { - ... - } - }The service implementation just implements the business - interface, nothing more. -
- -
- The extended business interface and the remote - interface - - // Extended business interface - public interface XService { - - public Result operation(SecurityContext securityCtx, Parameter param) throws SecurityServiceException, RemoteException; - } - - // Remote interface - public interface ServiceRemote extends XService, EJBObject {}The - extended business interface introduces an additional parameter for - each method (which is by convention the first parameter). Besides - that augmentation of the parameter list we have to consider that - this interface is being used in an EJB remoting scenario, so we - specify a "throws RemoteException" for each method. This is not - strictly necessary but it allows us to greatly simplify the - definition of the actual remote interface as could be seen in the - second listing. - - In addition to the RemoteException, each method also should - declare throwing a - org.springframework.security.ejb.server.SecurityServiceException. - This is because of the EJB spec: If an EJB method throws an - unchecked exception (all Spring Security exceptions are unchecked) - that exception will be wrapped into a RemoteException and the bean - instance will be dropped from the container. As this is unwanted - and negatively impacts performance we declare the - SecurityServiceException to be thrown. So any security exceptions - will be wrapped into a SecurityServiceException to be passed to - the client. Note that everything still works when that declaration - is omitted, but consider the negative consequences for the EJB in - question. -
- -
- The EJB implementation - - public class ServiceBean extends AbstractStatelessSessionBean implements XService { - - private static final long serialVersionUID = 1L; - - /** - * Delegate bean name. - */ - private static final String DELEGATE_BEAN_NAME = "xService"; - - /** - * The delegate. - */ - private XService delegate; - - - /** - * @see org.springframework.ejb.support.AbstractStatelessSessionBean#onEjbCreate() - */ - protected void onEjbCreate() throws CreateException { - this.delegate = (XService) getBeanFactory().getBean(DELEGATE_BEAN_NAME, XService.class); - } - - /** - * @see XService#operation(SecurityContext, Parameter) - */ - public Result operation(SecurityContext securityCtx, Parameter param) throws SecurityServiceException, RemoteException { - return this.delegate.operation(ctx, name); - } - } - - It is recommended to use the convenience - AbstractStatelessSessionBean base class provided by the Spring - Framework. Implementation is then reduced to implementing the - onEjbCreate()-callback method to retrieve the delegate bean and to - implement the methods to do the delegation. -
-
- -
- Wiring the client-side - - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> - - <beans> - - <bean id="client" class="client.Client"> - <property name="service" ref="service"/> - </bean> - - <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"> - <property name="environment"> - <value> - // ... - </value> - </property> - </bean> - - <bean id="service" class="org.springframework.security.ejb.client.SecurityContextInjectingRemoteSlsbProxyFactoryBean"> - - <property name="businessInterface" value="server.Service"/> - - <property name="slsbBusinessInterface" value="server.XService"/> - - <property name="jndiTemplate" ref="jndiTemplate"/> - - <property name="jndiName" value="ejb/Service"/> - - <property name="extraArgumentPosition" value="0"/> - - <property name="methodRegexpPatterns"> - <list> - <value>.*</value> - </list> - </property> - - </bean> - </beans>The above listing shows how the the service - is being wired to the client. Instead of using a - SimpleRemoteStatelessSessionProxyFactoryBean we use a - SecurityContextInjectingRemoteSlsbProxyFactoryBean which provides - the same functionality but is enhanced for hiding context - propagation. - - The specified "businessInterface" property designates the - actual business interface while the property "slsbBusinessInterface" - specifies the extended business interface (it conforms to the - SimpleRemoteStatelessSessionProxyFactoryBean#businessInterface - property). - - The "extraArgumentPosition" and "methodRegexpPatterns" - properties are optional. The former specifies the index of the - parameter to insert. The default is 0 which means that the - SecurityContext parameter will be the first one in the parameter - list. The latter parameter specifies which methods to enhance by an - additional SecurityContext parameter. By default all exposed methods - are enhanced. - - Most other properties correspond to those in - SimpleRemoteStatelessSessionProxyFactoryBean. Please refer to the - API documentation for more details. -
- -
- Wiring the server-side - - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> - - <beans> - - <!-- Proxy for extracting secure context information --> - <bean id="xService" class="org.springframework.security.ejb.server.support.SecurityContextExtractingProxyFactoryBean"> - - <property name="businessInterface" value="server.XService"/> - - <property name="interceptorNames"> - <list> - <value>serviceSecurityInterceptor</value> - </list> - </property> - - <property name="target" ref="serviceTarget"/> - - <property name="extraArgumentPosition" value="0"/> - - <property name="methodRegexpPatterns"> - <list> - <value>.*</value> - </list> - </property> - </bean> - - <!-- Security interceptor --> - <bean id="helloServiceSecurityInterceptor" class="org.springframework.security.ejb.server.support.TranslatingMethodSecurityInterceptor"> - <property name="validateConfigAttributes" value="true"/> - <property name="authenticationManager" ref="authenticationManager"/> - <property name="accessDecisionManager" ref="accessDecisionManager"/> - <property name="runAsManager" ref="runAsManager"/> - - <property name="objectDefinitionSource"> - <value>server.Service.*=ROLE_USER</value> - </property> - </bean> - - <!-- Service implementation --> - <bean id="serviceTarget" class="server.ServiceImpl"> - </bean> - - </beans> - - The definition of the EJB's delegate bean (xService) is - actually a SecurityContextExtractingProxyFactoryBean which creates a - proxy that takes care of extracting the SecurityContext, - establishing it, and delegating to the target bean - (serviceTarget). - - The "businessInterface" property is again the extended - business interface exposed by proxies created by the factory bean. - The "target" refers to the actual target bean, while the - "interceptorNames" property refers to a list of interceptor names - which have to be defined in the application context. - - Note that the security interceptor is of type - "TranslatingMethodSecurityInterceptor". It is a subclass of - org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor - and additionaly wraps all security exceptions into a - SecurityServiceException, if possible. For its parameterization - refer to the documentation of MethodSecurityInterceptor. - - The "extraArgumentPosition" and "methodRegexpPatterns" - properties are again optional, specifying the position of the - additional SecurityContext parameter and which methods will be - augmented by it. It is important that both properties are specified - the same on client and server. As recommendation just omit - specifying these properties and stick with the default - values. -
-
-