Announcement Announcement Module
Collapse
No announcement yet.
MethodSecurityInterceptor - method calls are not intercepted Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • MethodSecurityInterceptor - method calls are not intercepted

    Not sure what I'm missing here, but the service method calls are not intercepted based on user role (see Service Layer test below). All methods are called successfully regardless of who's making the call. Any guidance would be much appreciated.

    Here's my context file:
    ##################################################

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>
    <!-- ======================== FILTER CHAIN ======================= -->

    <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
    <property name="filterInvocationDefinitionSource">
    <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /**=httpSessionContextIntegrationFilter,logoutFilte r,authenticationProcessingFilter,securityContextHo lderAwareRequestFilter,rememberMeProcessingFilter, anonymousProcessingFilter,exceptionTranslationFilt er,filterInvocationInterceptor
    </value>
    </property>
    </bean>

    <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContex tIntegrationFilter"/>

    <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
    <constructor-arg value="/login_test/index.jsp"/> <!-- URL redirected to after logout -->
    <constructor-arg>
    <list>
    <ref bean="rememberMeServices"/>
    <bean class="org.acegisecurity.ui.logout.SecurityContext LogoutHandler"/>
    </list>
    </constructor-arg>
    <property name="filterProcessesUrl" value="/login_test/j_acegi_logout"/>
    </bean>

    <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationP rocessingFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="authenticationFailureUrl" value="/login_test/acegilogin.jsp?login_error=1"/>
    <property name="defaultTargetUrl" value="/"/>
    <property name="filterProcessesUrl" value="/login_test/j_acegi_security_check"/>
    <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>

    <bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHo lderAwareRequestFilter"/>

    <bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeP rocessingFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>

    <bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.Anony mousProcessingFilter">
    <property name="key" value="changeThis"/>
    <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
    </bean>

    <!-- ===================== HTTP REQUEST SECURITY ==================== -->

    <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFi lter">
    <property name="authenticationEntryPoint">
    <bean class="org.acegisecurity.ui.webapp.AuthenticationP rocessingFilterEntryPoint">
    <property name="loginFormUrl" value="/login_test/acegilogin.jsp"/>
    <property name="forceHttps" value="false"/>
    </bean>
    </property>
    <property name="accessDeniedHandler">
    <bean class="org.acegisecurity.ui.AccessDeniedHandlerImp l">
    <property name="errorPage" value="/login_test/accessDenied.jsp"/>
    </bean>
    </property>
    </bean>


    <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecur ityInterceptor">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="accessDecisionManager">
    <bean class="org.acegisecurity.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
    <list>
    <bean class="org.acegisecurity.vote.RoleVoter"/>
    <bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
    </list>
    </property>
    </bean>
    </property>
    <property name="objectDefinitionSource">
    <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /login_test/secure/extreme/**=ROLE_SUPERVISOR
    /login_test/secure/**=IS_AUTHENTICATED_REMEMBERED
    /**=IS_AUTHENTICATED_ANONYMOUSLY
    </value>
    </property>
    </bean>

    <!-- ======================== AUTHENTICATION ======================= -->

    <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedR ememberMeServices">
    <property name="userDetailsService" ref="userDetailsService"/>
    <property name="key" value="changeThis"/>
    </bean>

    <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager ">
    <property name="providers">
    <list>
    <ref local="daoAuthenticationProvider"/>
    <bean class="org.acegisecurity.providers.anonymous.Anony mousAuthenticationProvider">
    <property name="key" value="changeThis"/>
    </bean>
    <bean class="org.acegisecurity.providers.rememberme.Reme mberMeAuthenticationProvider">
    <property name="key" value="changeThis"/>
    </bean>
    </list>
    </property>
    </bean>

    <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenti cationProvider">
    <property name="userDetailsService" ref="userDetailsService"/>
    <property name="userCache">
    <bean class="org.acegisecurity.providers.dao.cache.EhCac heBasedUserCache">
    <property name="cache">
    <bean class="org.springframework.cache.ehcache.EhCacheFa ctoryBean">
    <property name="cacheManager">
    <bean class="org.springframework.cache.ehcache.EhCacheMa nagerFactoryBean"/>
    </property>
    <property name="cacheName" value="userCache"/>
    </bean>
    </property>
    </bean>
    </property>
    </bean>

    <bean id="userDetailsService" class="org.acegisecurity.userdetails.jdbc.JdbcDaoI mpl">
    <property name="dataSource"><ref bean="dataSource"/></property>
    <property name="usersByUsernameQuery">
    <value>select a.email, b.password, 'true' from persons a, users b where a.person_id = b.person_id and a.email = ?</value>
    </property>
    <property name="authoritiesByUsernameQuery">
    <value>select c.email, b.name from users a, groups b, persons c where a.group_id = b.group_id and a.person_id = c.person_id and c.email = ?</value>
    </property>
    </bean>

    <!-- ======================== SERVICE LAYER (test) ======================== -->
    <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy .BeanNameAutoProxyCreator" >
    <property name="interceptorNames">
    <list>
    <value>securityInterceptor</value>
    </list>
    </property>
    <property name="beanNames">
    <list>
    <value>testUserService</value>
    </list>
    </property>
    </bean>
    <bean id="securityInterceptor" class="org.acegisecurity.intercept.method.aopallia nce.MethodSecurityInterceptor">
    <property name="authenticationManager">
    <ref bean="authenticationManager" />
    </property>
    <property name="accessDecisionManager">
    <ref local="businessAccessDecisionManager" />
    </property>
    <property name="objectDefinitionSource">
    <value>
    <!-- assign approved roles to service methods -->
    xxx.xxx.xxx.service.UserService.findUser=ROLE_1
    xxx.xxx.xxx.service.UserService.deleteUser=ROLE_2
    </value>
    </property>
    </bean>
    <bean id="businessAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions"><value>false</value></property>
    <property name="decisionVoters">
    <list>
    <ref local="roleVoter" />
    </list>
    </property>
    </bean>
    <bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter" />
    <!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
    <bean id="loggerListener" class="org.acegisecurity.event.authentication.Logg erListener"/>
    </beans>
    ##################################################

    ...and an excerpt from web.xml
    ##################################################
    <filter>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
    <init-param>
    <param-name>targetClass</param-name>
    <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>


    ##################################################
    Last edited by wmm; Aug 24th, 2006, 10:18 AM.

  • #2
    Can you also provide the definition of the testUserServiceBean and the implementation of that bean?
    Besides that: Try setting the logging to DEBUG level to see if a proxy is applied to your bean at all.

    Regards,
    Andreas

    Comment


    • #3
      Here's the log:
      ################################
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Detected PATTERN_TYPE_APACHE_ANT directive; using Apache Ant style path expressions>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Detected CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON directive; Instructing mapper to convert URLs to lowercase before comparison>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Line 1: >
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Line 2: CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Line 3: PATTERN_TYPE_APACHE_ANT>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Line 4: /login_test/secure/extreme/**=ROLE_SUPERVISOR>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.PathBasedFilterInv ocationDefinitionMap] - <Added Ant path: /login_test/secure/extreme/**; attributes: [ROLE_SUPERVISOR]>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Line 5: /login_test/secure/**=IS_AUTHENTICATED_REMEMBERED>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.PathBasedFilterInv ocationDefinitionMap] - <Added Ant path: /login_test/secure/**; attributes: [IS_AUTHENTICATED_REMEMBERED]>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Line 6: /**=IS_AUTHENTICATED_ANONYMOUSLY>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.PathBasedFilterInv ocationDefinitionMap] - <Added Ant path: /**; attributes: [IS_AUTHENTICATED_ANONYMOUSLY]>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.web.FilterInvocationDe finitionSourceEditor] - <Line 7: >
      2006-08-24 09:32:28,942 INFO [org.acegisecurity.intercept.AbstractSecurityInterc eptor] - <Validated configuration attributes>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.method.MethodDefinitio nMap] - <Adding secure method [xxx.xxx.xxx.service.UserService.deleteUser] with attributes [[ROLE_2]]>
      2006-08-24 09:32:28,942 INFO [org.acegisecurity.intercept.method.MethodDefinitio nMap] - <Adding secure method [public abstract void xxx.xxx.xxx.service.UserService.deleteUser(java.la ng.Integer)] with attributes [[ROLE_2]]>
      2006-08-24 09:32:28,942 DEBUG [org.acegisecurity.intercept.method.MethodDefinitio nMap] - <Adding secure method [xxx.xxx.xxx.service.UserService.findUser] with attributes [[ROLE_1]]>
      2006-08-24 09:32:28,942 INFO [org.acegisecurity.intercept.method.MethodDefinitio nMap] - <Adding secure method [public abstract xxx.xxx.xxx.domain.user.User xxx.xxx.xxx..service.UserService.findUser(java.lan g.Integer)] with attributes [[ROLE_1]]>
      2006-08-24 09:32:28,958 INFO [org.acegisecurity.intercept.AbstractSecurityInterc eptor] - <Validated configuration attributes>
      2006-08-24 09:32:28,958 DEBUG [org.acegisecurity.intercept.AbstractSecurityInterc eptor] - <Public object - authentication not attempted>
      2006-08-24 09:32:28,958 DEBUG [org.acegisecurity.intercept.AbstractSecurityInterc eptor] - <Public object - authentication not attempted>
      2006-08-24 09:32:28,958 DEBUG [org.acegisecurity.intercept.AbstractSecurityInterc eptor] - <Public object - authentication not attempted>
      ################################

      ...and the interface
      ################################
      package xxx.yyy.zzz;

      import java.util.List;

      /*
      imports...
      */

      public interface UserService
      {
      public User findUser(Integer id);
      public void deleteUser(Integer id);
      }

      ################################
      ...and the implementation
      ################################
      /**
      *
      */
      package xxx.yyy.zzz;

      public class TestUserServiceDefault implements UserService
      {
      public User findUser(Integer id)
      {
      System.out.println("findUser called");
      return null;
      }

      public void deleteUser(Integer id)
      {
      System.out.println("deleteUser called");
      }
      }

      ################################

      Comment


      • #4
        Hmm. At first glance it seems ok to me. The log seems to indicate, that the configured roles are applied correctly to the methods.
        Perhaps the lookup of the user roles via the DAO does yield unexpected results?
        What roles do you have after authentication? Or can you invoke the methods also without authentication?

        For simplifying things, maybe you could temporarily remove all authentication providers except the DAO provider.

        Regards,
        Andreas

        Comment


        • #5
          Andreas,

          Thank you for your quick reply. I have performed a couple of tests and found the following:

          1. I changed the userDetailsService configuration to use InMemoryDaoImpl rather than JdbcDaoImpl and explicitly set the username, password and role in the context file. The methods are still not protected. So I don't think that the role lookup is an issue.

          2. I moved the calls to the methods to a public page (without authentication). The methods were still not protected. All methods were called successfully.

          Perhaps the issue lies with how I am making the call to the methods? I was under the impression that any call would be intercepted. Here is how I am making the call:
          #############################
          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("...path to context file...");
          UserService userService = (UserService)applicationContext.getBean("testUserS ervice");
          ...
          userService.findUser(2);
          userService.deleteUser(2);
          ...
          #############################
          ...and the bean definition (TestUserServiceDefault is the implementation class)
          #############################
          <bean id="testUserService" parent="<parent bean>">
          <property>
          <bean class="xxx.xxx.xxx.service.TestUserServiceDefault" />
          </property>
          </bean>
          #############################

          Comment


          • #6
            I agree that the role lookup doesn't seem to be the problem then.

            As the previous logs indicate, a proxy has been created. Maybe double-check it by outputting userService.getClass() after getting it from the app context. Should be something like $Proxy1.

            Besides that, I would suggest to debug into the method invocation (e.g. findUser()) to check what really happens. Especially important would be the Authentication object and which GrantedAuthorities it stores.

            Regards,
            Andreas

            Comment


            • #7
              Ok I seemed to have found the issue, although not the reason why. The definition of "testUserService" was configured by extending TransactionProxyFactoryBean which takes HibernateTransactionManager as a property. Not sure why, but apparently this interceptor bypasses any protected methods and exposes all methods. However, if I simply configure the bean (id and class) without any transactions, the methods are protected. Any ideas?

              Thanks.

              Comment


              • #8
                Strange. Can you please post the complete configuration of "testUserService" and its parent bean(s)?

                Regards,
                Andreas

                Oh, and by the way: code is better readable when included in [ c o d e ] [/c o d e] tags (without the blanks).

                Comment


                • #9
                  Did you ever find out why your MethodSecurityInterceptor did not get invoked?

                  Comment


                  • #10
                    It would be useful to see the complete logs here. I'm not sure if the previous log was detailing the URL or method protection.

                    Comment


                    • #11
                      Hi Karl,
                      Thanks for your response. Here is my applicationContext.xml

                      Code:
                      	<bean id="txProxyParent" abstract="true"
                      		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                      		<property name="transactionManager" ref="transactionManager" />
                      		<property name="transactionAttributes">
                      			<props>
                      				<prop key="save*">PROPAGATION_REQUIRED</prop>
                      			</props>
                      		</property>
                      	</bean>
                      
                      	<bean id="studentService" parent="txProxyParent">
                      		<property name="target">
                      			<bean class="XXX.XXX.XXXX.StudentService">
                      				<property name="emailService" ref="emailService" />
                      			</bean>
                      		</property>
                      	</bean>
                      	
                      	<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
                      		<property name="interceptorNames">
                      			<list>
                      				<value>serviceLayerSecurityInterceptor</value>
                      			</list>
                      		</property>
                      		<property name="beanNames">
                      			<list>
                      				<value>studentService</value>
                      			</list>
                      		</property>
                              <property name="proxyTargetClass" value="true"/>		
                      	</bean>	
                      	
                      	<bean id="serviceLayerSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
                      		<property name="authenticationManager"><ref bean="authenticationManager"/></property>
                      		<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
                      		<property name="objectDefinitionSource">
                      			<value>
                      				XXX.XXX.XXXX.StudentService.saveOrUpdateStudent=ROLE_TEACHER
                      			</value>
                      		</property>
                      	</bean>
                      Now, I can see that the proxy gets created when I start the server, I see the following in the log.
                      DEBUG | 2007-04-12 22:30:59,698 | org.springframework.aop.framework.autoproxy.BeanNa meAutoProxyCreator | Creating implicit proxy for bean 'studentService' with 1 common interceptors and 0 specific interceptors.

                      Now, when the saveOrUpdateStudent is invoked (I have a role of ROLE_STUDENT), the call goes thru sucessfully (I set a breakpoint on MethodSecurityInterceptor.invoke(), the breakpoint is never hit).

                      But when I remove the parent="txProxyParent" from the studentService bean definition, everything seems fine.

                      Thoughts?

                      Comment


                      • #12
                        Instead of using the auto wiring bean, I would have a look at the pre and post interceptors. As you are already proxying the object with TransactionProxyFactoryBean it might make sense to add the security there.
                        http://www.springframework.org/docs/....Object&#91;])

                        Comment


                        • #13
                          Sadly, I am not using Spring 2.0. The AbstractSingletonProxyFactoryBean is not available in Spring 1.2.8.

                          Comment


                          • #14
                            The same concept of pre and post interceptors existed in Spring 1.x.
                            http://static.springframework.org/sp....Object&#91;])

                            Comment

                            Working...
                            X