Announcement Announcement Module
Collapse
No announcement yet.
Howe to make method interception really works Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Howe to make method interception really works

    Hello all,

    I have spent more than two weeks trying to get Method Interception and ACL to work but in vain.. well.. let's not jump to the ACL part because the security interceptor doesn't even get triggered to check for the correct ACE.. the question is if method interception would ever really work??

    I have tried CGLIB proxying and Java Proxying.. and even though CGLIB proxying seems to cause the method interception to work sometimes I had to abandon it because it didn't work with
    <aop:scoped-proxy />
    and I kept getting the same proxy object for all HTTP sessions.. now I use
    <aop:scoped-proxy proxy-target-class="false"/>
    which requires Java interface proxying but at least gives me different Beans for different sessions.

    I have also tried global point cuts, annotations, and the sec namespace XML to define the method inteception.. but all was in vain.

    Any ideas?

    My project uses IceFaces 1.8 with Facelets, Spring Security 2.0.8, and runs on Apache Tomcat 6 and JRE 6.18. The interesting part of the configuration file follows:


    HTML Code:
    	<bean id="wfaclDecisionManager" class="org.springframework.security.vote.UnanimousBased">
    		<property name="allowIfAllAbstainDecisions" value="false" />
    		<property name="decisionVoters">
    			<list>
    				<bean id="roleVoter" class="org.springframework.security.vote.RoleVoter" />
    				<ref local="wfaclCREATEVoter" />
    				<ref local="wfaclEDITVoter" />
    				<ref local="wfaclRELEASEVoter" />
    				<ref local="wfaclDELETEVoter" />
    			</list>
    		</property>
    	</bean>
    
    	<bean id="wfaclCREATEVoter" class="org.springframework.security.vote.AclEntryVoter">
    		<constructor-arg ref="aclService" />
    		<constructor-arg value="WFACL_CREATE" />
    		<constructor-arg>
    			<list>
    				<util:constant
    					static-field="org.bibalex.workflow.storage.WFSVNClientPermission.WFACL_CREATE" />
    			</list>
    		</constructor-arg>
    		<property name="processDomainObjectClass" value="org.bibalex.workflow.storage.SVNFileCreationProtectionArtifact"/>
    	</bean>
    
    <!-- And other entry voters ommitted -->
    	<!--
    		****** Workflow Definition ******
    	-->
    	<bean id="wfStepCREATE" class="org.bibalex.workflow.WFInitiationStep"
    		lazy-init="true">
    
    		<property name="creationProtectionClass"
    			value="org.bibalex.workflow.storage.SVNFileCreationProtectionArtifact" />
    
    		<property name="stepPermission">
    			<util:constant
    				static-field="org.bibalex.workflow.storage.WFSVNClientPermission.WFACL_CREATE" />
    		</property>
    		<property name="stepRole" value="ROLE_CREATOR" />
    
    		<property name="nextStepMap">
    			<map>
    				<entry key="PROCEED" value="EDIT" />
    			</map>
    
    		</property>
    <!--  DON'T DO IT! -->	
    <!--		<sec:intercept-methods-->
    <!--			access-decision-manager-ref="wfaclDecisionManager">-->
    <!--			<sec:protect-->
    <!--				method="complete"-->
    <!--				access="ROLE_CREATOR,WFACL_CREATE" />-->
    <!--		</sec:intercept-methods>-->
    	</bean>
    
    	<bean id="wfStepEDIT" class="org.bibalex.workflow.WFStep"
    		lazy-init="true">
    		<property name="stepPermission">
    			<util:constant
    				static-field="org.bibalex.workflow.storage.WFSVNClientPermission.WFACL_EDIT" />
    		</property>
    		<property name="stepRole" value="ROLE_EDITOR" />
    
    		<property name="nextStepMap">
    			<map>
    				<entry key="PROCEED" value="RELEASE" />
    			</map>
    		</property>
    	
    		<sec:intercept-methods
    			access-decision-manager-ref="wfaclDecisionManager">
    			<sec:protect
    				method="complete"
    				access="ROLE_EDITOR,WFACL_EDIT" />
    		</sec:intercept-methods>
    	</bean>
    
    	<bean id="wfStepRELEASE" class="org.bibalex.workflow.WFStep"
    		lazy-init="true">
    		<property name="stepPermission">
    			<util:constant
    				static-field="org.bibalex.workflow.storage.WFSVNClientPermission.WFACL_RELEASE" />
    		</property>
    		<property name="stepRole" value="ROLE_RELEASER" />
    
    		<property name="nextStepMap">
    			<map>
    				<entry key="ACCEPT" value="DONE" />
    				<entry key="REJECT" value="EDIT" />
    			</map>
    		</property>
    		<sec:intercept-methods
    			access-decision-manager-ref="wfaclDecisionManager">
    			<sec:protect
    				method="complete"
    				access="ROLE_RELEASER,WFACL_RELEASE" />
    		</sec:intercept-methods>
    	</bean>
    
    	<bean id="wfStepDONE" class="org.bibalex.workflow.WFTerminationStep"
    		lazy-init="true">
    	</bean>
    
    
    
    	<!--  ********  WFProcessObject *******  -->
    	<bean id="wamcpWFProcess" class="org.bibalex.workflow.WFProcess"
    		lazy-init="true">
    		<constructor-arg ref="aclService" /> <!--  <property name="aclSvc" ref="aclService"/> -->
    		<constructor-arg ref="wamcpAppDataSource" /> <!-- <property name="datasource" ref="wamcpAppDataSource" /> -->
    		<constructor-arg ref="aclSecurityUtil" />
    		<property name="steps">
    			<map>
    				<entry key="INIT" value-ref="wfStepCREATE" />
    				<entry key="EDIT" value-ref="wfStepEDIT" />
    				<entry key="RELEASE" value-ref="wfStepRELEASE" />
    				<entry key="DONE" value-ref="wfStepDONE" />
    			</map>
    		</property>
    	</bean>
    
    	<!-- ****************** enforcing the workflow ***************** -->
    
    	<!--  This didn't work.. neither the annotations or the pointcuts :D -->
    	<!-- LOOOOOOOOOOOOOL -->	
    	<!--	<sec:global-method-security-->
    	<!--		secured-annotations="enabled"-->
    	<!--		access-decision-manager-ref="wfaclDecisionManager" >-->
    <!---->
    	<!--		<sec:protect-pointcut -->
    	<!--			access="ROLE_CREATOR, WFACL_CREATE" -->
    	<!--
    		expression="execution(*
    		org.bibalex.wamcp.application.WAMCPStorage.add(..))"/>
    	-->
    	<!--	</sec:global-method-security>-->
    
    	<bean class="org.bibalex.workflow.storage.WFSVNClient" id="wfsvnClient"
    		scope="session" lazy-init="true">
    		
    		<aop:scoped-proxy proxy-target-class="false"/>
    	
    		<property name="URL_SVN_ROOT" value="PROTECTED" />
    		<property name="svnUsername" value="PROTECTED.naga" />
    		<property name="svnPassword" value="PROTECTED" />
    		<property name="wfProcess" ref="wamcpWFProcess" />
    		
    		<sec:intercept-methods
    			access-decision-manager-ref="wfaclDecisionManager">
    			<sec:protect
    				method="svn*"
    				access="ROLE_SVNACCESSOR"/>
    			<sec:protect
    				method="add"
    				access="ROLE_CREATOR,WFACL_CREATE" />
    			<sec:protect
    				method="openWrite"
    				access="ROLE_EDITOR,WFACL_EDIT" />
    			<sec:protect
    				method="openRead"
    				access="ROLE_SVNACCESSOR" />
    			<sec:protect
    				method="svnCommit"
    				access="ROLE_EDITOR,WFACL_EDIT" />
    			<sec:protect
    				method="svnRevert"
    				access="ROLE_EDITOR,WFACL_EDIT" />
    <!--			<sec:protect-->
    <!--				method="permitDelete"-->
    <!--				access="ROLE_ADMIN" />-->
    			<sec:protect
    				method="delete"
    				access="ROLE_ADMIN,WFACL_DELETE" />
    			<sec:protect
    				method="requestDelete"
    				access="ROLE_DELETER" />
    			<sec:protect
    				method="unrequestDelete"
    				access="ROLE_DELETER" />
    		</sec:intercept-methods>
    		
    		<property name="proxiedThis" ref="wfsvnClient" />
    		
    	</bean>
    Any help would be greatly appreciated

  • #2
    That you receive the same proxy is basically correct. You will get a aop-scoped proxy which lazily delegates to the actual session scoped object. That proxy is the same for everyone.

    Another problem you have is that you have a circulair dependency which probably (or at least might) prevent proper proxy creation.

    Code:
    <property name="proxiedThis" ref="wfsvnClient" />
    You are also using jsf (IceFaces) make sure that you use the spring configured objects and NOTjsf managed the objects, which would basically render your spring configuration useless.

    Comment


    • #3
      Hello Martin,

      Thanks for the quick reply.

      As for "You are also using jsf (IceFaces) make sure that you use the spring configured objects and NOTjsf managed the objects, which would basically render your spring configuration useless"... I use only Spring IoC managed beans

      As for the circular dependency.. I actually created it to try to work around that the method interception doesn't work in the cases where I am calling some of the protected methods from the object itself (i don't know if proxying is done by delegation or by inheritence so I wasn't sure what "this" refers tomy object or the proxy) But, this doesn't mean that method interception worked in other cases.. it is just as if it is not there.

      Any other ideas?

      Comment


      • #4
        As for the circular dependency.. I actually created it to try to work around that the method interception doesn't work in the cases where I am calling some of the protected methods from the object itself (i don't know if proxying is done by delegation or by inheritence so I wasn't sure what "this" refers tomy object or the proxy) But, this doesn't mean that method interception worked in other cases.. it is just as if it is not there.
        This reference will lead to eager creation of the bean bypassing proxy creation or at least partially bypassing it, which will eventually lead to issues.

        As for "You are also using jsf (IceFaces) make sure that you use the spring configured objects and NOTjsf managed the objects, which would basically render your spring configuration useless"... I use only Spring IoC managed beans
        In which way are you enforcing this? And are you 100% sure?

        I suggest for starters to remove the ACL stuff to get a testcase as small as possible. Can you post your full configuration (applicationcontext xml files and web.xml? you can put them in a zip file and attach them).

        Comment


        • #5
          Marten,

          Thank you very much.. attached are the configuration files.

          But could you please also tell me if I need to have something similar to my "circular dependency" hack (maybe refactoring into two classes) to insure that method calls from the object itself (using this) will be protected as well?

          Comment


          • #6
            I suggest a read of the reference guide especially the AOP chapter. Spring uses delegation, so this is called on the UNPROXIED instance.

            Comment


            • #7
              I had to do this reading very quickly.. I know it is a difficult subject but my time was so limited.. so I will make sure not to use this.. but still please take a look at the files attached to see if there are other pitfalls in which I had fallen

              Comment


              • #8
                You seem to use a lot of session/request scoped beans, for those to properly work you must use aop:scoped-proxy, without it generally acts like scope prototype. Not sure but some of those beans are candidates for singletons imho (like the manager classes for instance).

                The secured methods, as you are using interface based proxies, have to be defined on the interface if not it will not work. Also if you want to @Secured work you will have to put them on the classes and force classproxying else you will run into trouble.
                Last edited by Marten Deinum; Jul 21st, 2010, 06:20 AM.

                Comment


                • #9
                  The secured methods, as you are using interface based proxies, have to be defined on the interface if not it will not work.
                  Uhuhh... now that is something. I was actually using CGLIB proxying until I discovered that it causes the re-use of the same object in all sessions and switched to the Interface proxying.. probably that is where things started to go wrong. Because as I said before, with CGLIB proxying method interception was working in some cases (and not working in the cases where I call using this)... now method interception doesn't work at all.

                  So could you please tell me how to define them on the interface? I would like to keep this in the configuration file if possible.. that is, not using the Secured annotations.. because this is part of a reusable Workflow Library.

                  Comment


                  • #10
                    As I mentioned earlier that you get the SAME object is CORRECT... It is a single object which lazily delegates to the ACTUAL session scoped object. So what you think is wrong isn't wrong, your thinking is flawed... IMHO you had it working.

                    That the security isn't invoked on this calls common knowledge and stems from the time of EJB. It basically has to do with the fact that proxies are involved. However if you start injecting a this reference you will get eager object creation, which might lead to bypass proxy creation.

                    What I meant with define them on the interface is that the methods you want to secure have to be part of your interface...

                    Comment


                    • #11
                      Marten,

                      Please bear with me and just tell me how to define the method security on the interface without using the @secured annotation.

                      Thank you!

                      Comment


                      • #12
                        Sigh... As I stated and I assume you know how to define an interface?!

                        ...the methods you want to secure have to be part of your interface...

                        Comment


                        • #13
                          Ok.. now that brings us back to our start point... because they are part of the interface.. I thought you meant that the security interception definition should be part of the interface.

                          What I will do is that I will try removing the circular reference.. but that was a hack to fix the problemt that I had from the very begining... and no.. I didn't have it working.. because I was getting the same Object in all sessions and not the same Proxy.. so all the users will use the Object of the first user.. not the only the proxy.

                          Thank you for your time... and please, just relax!

                          Comment

                          Working...
                          X