Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: After Invocation Collection Filtering From an EJB (Stateless Session Bean)

  1. #1
    Join Date
    Aug 2011
    Posts
    11

    Question After Invocation Collection Filtering From an EJB (Stateless Session Bean)

    Hi,

    I am working on a proof of concept to integrate spring security into our J2EE application. I would like to use ACL to filter out search results from a returned collection. I looked through the dms example and found out about the AclEntryAfterInvocationCollectionFilteringProvider and its configuration. This would do exactly what I want but the problem is that the class containg the method to intercept is an EJB (a Stateless Session Bean).

    This application is deployed on a Weblogic 10.3.4 server as an ear. I have followed the steps to propagate the application context in the jar containing the ejb (http://blog.springsource.com/2007/06...g-application/). Here is what the ear looks like:

    my-app.ear
    ---web-client.war
    ------WEB-INF
    ---------web-context.xml
    ---------web.xml
    ---------...
    ---ejb-modules.jar
    ------beanRefContext.xml
    ------ejb-context.xml
    ------some/path/ClientAPI
    ------some/path/ClientAPIBean
    ------...
    ---...

    I looked at the available jee tags to lookup an EJB from JNDI and came up with the following line (in ejb-context.xml):

    Code:
    	
    ...
    	<jee:local-slsb id="clientAPIBean"
    		jndi-name="clientAPIBean#some.path.ClientAPI"
    		business-interface="some.path.ClientAPI" />
    ...
    Here is a snippet from web-context.xml which defines the MethodSecurityInterceptor and its dependencies:

    Code:
    ...
    	<bean id="methodSecurityInterceptor" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
    		<property name="authenticationManager">
    			<ref bean="authenticationManager" />
    		</property>
    		<property name="accessDecisionManager">
    			<ref local="businessAccessDecisionManager" />
    		</property>
    		<property name="afterInvocationManager">
    			<ref local="afterInvocationManager" />
    		</property>
    		<property name="securityMetadataSource">
    			<value>
    			some.path.ClientAPI.retrieveAllItems=AFTER_ACL_COLLECTION_READ
    			</value>
    		</property>
    	</bean>
    ...
    Note that the some.path.ClientAPI EJB is used in a value tag so I cannot use the reference to the EJB I created in ejb-context.xml.

    After deploying the ear in Weblogic my log4j log states that beans are getting created and configured properly with no exceptions. The logs also state that spring successfully retireved the some.path.ClientAPI EJB from JNDI

    However, when the retrieveAllItems method is executed nothing gets printed to my log4j log as if the interceptor did not get called.

    What are my doing wrong? How would I get the MethodSecurityInterceptor to actually do something?

    Thank you!
    Last edited by McDuff; Aug 22nd, 2011 at 04:10 PM. Reason: clarifications

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    Only configuring the MethodSecurityInterceptor isn't going to do much if you don't create a proxy which actually uses that interceptor. I suggest using the namespace instead of the classes, it saves you a lot of configuration. Also make sure that the method security is configured in the same application context that is used to create/retrieve the EJB else proxying isn't going to happen.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Aug 2011
    Posts
    11

    Question MethodSecurityInterceptor still not triggered after calling my secured ejb method!

    Thank you for the reply.

    Following your suggestion I changed the ear's directory tree so my application context is contained in a single file (context.xml):

    my-app.ear
    ---web-client.war
    ------WEB-INF
    ---------web.xml
    ---------...
    ---ejb-modules.jar
    ------beanRefContext.xml
    ------context.xml
    ------some/path/ClientAPI
    ------some/path/ClientAPIBean
    ------...
    ---...

    Here is a snippet of my web.xml:
    Code:
    	
    ...
    	<context-param>
    		<param-name>parentContextKey</param-name>
    		<param-value>context</param-value>
    	</context-param>
    
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value></param-value>
    	</context-param>
    	
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    	
    	<listener>
    	    	<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    	</listener>
    ...
    This has the effect looking for the beanRefContext.xml file in the ejb-modules.jar which contains the ejb to secure. Here is the content of beanRefContext.xml:
    Code:
    	
    ...
    	<bean id="context" class="org.springframework.context.support.ClassPathXmlApplicationContext">
    	    <constructor-arg>
    	        <list>
    	            <value>context.xml</value>
    	        </list>
    	    </constructor-arg>
    	</bean>
    ...
    context.xml, which contains all bean and security entries, is now getting used as the spring application context.

    Following your other suggestion, I added a proxy that uses my security method interceptor. Here is a snippet from context.xml:
    Code:
    	
    ...
    	
    	<jee:local-slsb id="clientAPIBean"
    		jndi-name="clientAPIBean#some.path.ClientAPI"
    		business-interface="some.path.ClientAPI" />
    
    	<bean id="methodSecurityMetadataSourceAdvisor"
    		class="org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor">
    		<constructor-arg ref="methodSecurityInterceptor" />
    	</bean>
    
    	<bean
    		class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
    		id="defaultAdvisorAutoProxyCreator">
    		<property name="beanName" value="methodSecurityMetadataSourceAdvisor" />
    	</bean>
    
    	<bean id="methodSecurityInterceptor"
    		class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
    		<property name="authenticationManager">
    			<ref bean="authenticationManager" />
    		</property>
    		<property name="accessDecisionManager">
    			<ref local="businessAccessDecisionManager" />
    		</property>
    		<property name="afterInvocationManager">
    			<ref local="afterInvocationManager" />
    		</property>
    		<property name="securityMetadataSource">
    			<value>
    				some.path.ClientAPI.retrieveAllItems=AFTER_ACL_COLLECTION_READ
    			</value>
    		</property>
    	</bean>
    
    	<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter" />
    
    	<bean id="businessAccessDecisionManager"
    		class="org.springframework.security.access.vote.AffirmativeBased">
    		<property name="allowIfAllAbstainDecisions" value="true" />
    		<property name="decisionVoters">
    			<list>
    				<ref local="roleVoter" />
    			</list>
    		</property>
    	</bean>
    
    	<security:global-method-security
    		access-decision-manager-ref="businessAccessDecisionManager">
    	</security:global-method-security>
    ...
    When I deployed the ear to Weblogic, the log4j log still looks ok:
    Code:
    	
    ...
    [org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean] Located object with JNDI name [java:comp/env/ClientAPIBean#some.path.ClientAPI]
    [org.springframework.aop.framework.JdkDynamicAopProxy] Creating JDK dynamic proxy: target source is EmptyTargetSource: no target class, static
    [org.springframework.beans.factory.support.DefaultListableBeanFactory] Finished creating instance of bean 'clientAPIBean'
    ...
    [org.springframework.web.context.ContextLoader] Root WebApplicationContext: initialization completed in 4141 ms
    ...
    If I used my web UI to go through the use case where the some.path.ClientAPI.retrieveAllItems method is called, the log4j log does not show any other messages. I would expect to see method security interceptor related messages. Once again, it is not getting called.

    Is there anything else I can try?

    Thank you!

    PS: About your suggestion on using namespace style configuration, I did not find an application context descriptor in samples/examples that uses that style to declare method security interceptors and its dependencies. Do you know about any sample/example that would do such a thing?

    Also, I had a look at this page. How would I use the global-method-security to declare my interceptor?

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    Currently you are mixing 2 strategies which I guess interfere with each other..

    Namespace configuration
    Code:
    <security:global-method-security
    		access-decision-manager-ref="businessAccessDecisionManager">
    	</security:global-method-security>
    Plain configuration
    Code:
    </bean>
    
    	<bean
    		class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
    		id="defaultAdvisorAutoProxyCreator">
    		<property name="beanName" value="methodSecurityMetadataSourceAdvisor" />
    	</bean>
    
    	<bean id="methodSecurityInterceptor"
    		class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
    		<property name="authenticationManager">
    			<ref bean="authenticationManager" />
    		</property>
    		<property name="accessDecisionManager">
    			<ref local="businessAccessDecisionManager" />
    		</property>
    		<property name="afterInvocationManager">
    			<ref local="afterInvocationManager" />
    		</property>
    		<property name="securityMetadataSource">
    			<value>
    				some.path.ClientAPI.retrieveAllItems=AFTER_ACL_COLLECTION_READ
    			</value>
    		</property>
    	</bean>
    
    	<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter" />
    
    	<bean id="businessAccessDecisionManager"
    		class="org.springframework.security.access.vote.AffirmativeBased">
    		<property name="allowIfAllAbstainDecisions" value="true" />
    		<property name="decisionVoters">
    			<list>
    				<ref local="roleVoter" />
    			</list>
    		</property>
    	</bean>
    I suggest the namespace and remove all plain configuration (for as far it isn't needed).

    Code:
    <security:global-method-security access-decision-manager-ref="businessAccessDecisionManager" after-invocation-provider="afterInvocationProvider">
      <security:protect-pointcut expression="execution(* some.path.ClientAPI+.retrieveAllItem(..))" access="AFTER_ACL_COLLECTION_READ" />
    </security:global-method-security>
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5
    Join Date
    Aug 2011
    Posts
    11

    Question Still not working

    Thanks for your help Marten.

    I tried the namespace based configuration and my after invocation filtering still does not get triggered. I will continue to investigate and reply with more details later.

    I had another question. Is the jee:local-slsb tag in my initial configuration required? If so how does spring AOP knows to use the ejb retired via JNDI?

    Thanks again!
    Last edited by McDuff; Aug 24th, 2011 at 11:33 AM.

  6. #6
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    I had another question. Is the jee:local-slsb tag in my initial configuration required? If so how does spring AOP knows to use the ejb retired via JNDI?
    Well actually it doesn't know anything about the ejb, it knows that there is an object which implements the ClientAPI interface (a dynamically created proxy which handles all the ugly ejb stuff).

    Which makes me wonder that could be very well be the problem (because it is already a proxy), what you could try is create a simply bean that implements the ClientAPI interface and see what happens (just as a test).

    Another thing you can do is throw a (Runtime)Exception from the method mentioned and see if the MethodSecurity is applied (the interceptor should then show up in the stack trace).
    Last edited by Marten Deinum; Aug 24th, 2011 at 01:55 PM.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  7. #7
    Join Date
    Aug 2011
    Posts
    11

    Default

    I threw a RuntimeException from the method to secure. The following is a snippet of the stack trace. The trace is identical if I use the jee tag to declare my ejb or if I don't declare it at all.

    Code:
            at com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
            at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
            at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
            at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
            at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
            at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
            at com.bea.core.repackaged.springframework.jee.spi.MethodInvocationVisitorImpl.visit(MethodInvocationVisitorImpl.java:37)
            at weblogic.ejb.container.injection.EnvironmentInterceptorCallbackImpl.callback(EnvironmentInterceptorCallbackImpl.java:54)
            at com.bea.core.repackaged.springframework.jee.spi.EnvironmentInterceptor.invoke(EnvironmentInterceptor.java:50)
            at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
            at com.bea.core.repackaged.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
            at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
            at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
            at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
            at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
            at com.bea.core.repackaged.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    I might try your other suggestion later. Right now I'm looking at manually invoking the decide method of AclEntryAfterInvocationCollectionFilteringProvider from my method.

    Thanks!

  8. #8
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    I threw a RuntimeException from the method to secure. The following is a snippet of the stack trace. The trace is identical if I use the jee tag to declare my ejb or if I don't declare it at all.
    If it is exactly the same how do you get the ejb? Can you show me the code which is calling the ejb? Because it it doesn't make any difference that would indicate to me you aren't using the beans declared in your application context...
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  9. #9
    Join Date
    Aug 2011
    Posts
    11

    Default

    If it is exactly the same how do you get the ejb?
    Code:
    	<jee:local-slsb id="clientAPIBean"
    		jndi-name="clientAPIBean#some.path.ClientAPI"
    		business-interface="some.path.ClientAPI" />
    Because if it doesn't make any difference that would indicate to me you aren't using the beans declared in your application context...
    It does not make a difference because I do not know how to tell the AOP pointcut expression to use the ejb that was imported into the spring context. I presumed that the AOP pointcut expression would be smart enough to know it had to use my imported ejb. I had that concern in a previous post:

    I had another question. Is the jee:local-slsb tag in my initial configuration required? If so how does spring AOP knows to use the ejb retired via JNDI?
    Anyways, here is my config at the moment:

    Code:
    ...
    	<security:global-method-security
    		access-decision-manager-ref="accessDecisionManager">
    		<security:protect-pointcut
    			expression="execution(* some.path.ClientAPI+.retrieveItems(..))"
    			access="ALWAYS_GRANT" />
    		<security:after-invocation-provider
    			ref="afterAclCollectionRead" />
    	</security:global-method-security>
    
    	<jee:local-slsb id="clientAPIBean"
    		jndi-name="clientAPIBean#some.path.ClientAPI"
    		business-interface="some.path.ClientAPI" />
    
    	<bean id="accessDecisionManager"
    		class="org.springframework.security.access.vote.AffirmativeBased">
    		<property name="decisionVoters">
    			<list>
    				<ref local="alwaysGrantAccessVoter" />
    			</list>
    		</property>
    	</bean>
    
    	<bean id="alwaysGrantAccessVoter" class="some.path.AlwaysGrantAccessVoter" />
    
    	<bean id="afterAclCollectionRead"
    		class="org.springframework.security.acls.afterinvocation.AclEntryAfterInvocationCollectionFilteringProvider">
    		<constructor-arg ref="aclService" />
    		<constructor-arg>
    			<list>
    				<ref local="aclReadPermission" />
    			</list>
    		</constructor-arg>
    	</bean>
    
    	<bean id="aclReadPermission"
    		class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
    		<property name="staticField">
    			<value>org.springframework.security.acls.domain.BasePermission.READ
    			</value>
    		</property>
    	</bean>
    ...
    If you require more snippets let me know!

    Thanks!

  10. #10
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    It does not make a difference because I do not know how to tell the AOP pointcut expression to use the ejb that was imported into the spring context. I presumed that the AOP pointcut expression would be smart enough to know it had to use my imported ejb. I had that concern in a previous post:
    You stated that if you remove the jee stuff from the context the stack trace is the same... I want to know HOW do you use/access the clientAPI from your code... My guess is that you do not use this.So which bean do you wire the bean named 'clientAPIBean' into.

    Is it possible for you to attach the whole project? Or is that going to be problematic, if you want I can PM you my email so you can send it to me privately.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •