Announcement Announcement Module
Collapse
No announcement yet.
Can't get PreAuthorize annotation to work with CustomPermEvaluator Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can't get PreAuthorize annotation to work with CustomPermEvaluator

    Command used to test
    Code:
    curl -ik -H "SM_USER: scott" -X GET http://127.0.0.1:8080/auth/rest/auth/primitive/StringArray/
    At this point, it returns correctly. I would have expected some sort of failure from the preauthorized annotations. The user 'scott' has neither ROLE_SUPERVISOR nor permission to write.
    Furthmore, the CustomPermissionEvaluator does not seem to be called since none of its logging is visible. I can get intercept-url to work with hasRole() but not the PreAuthorize annotation.

    Am I missing something obvious as to why my @PreAuthorize doesn't seem to be doing anything?

    my web.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/spring/*-config.xml
            </param-value>
        </context-param>
    
        <filter>
            <filter-name>springSecurityFilterChain</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>springSecurityFilterChain</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <servlet>
            <servlet-name>rest</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>2</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>rest</servlet-name>
            <url-pattern>/rest/*</url-pattern>
        </servlet-mapping>
    
    
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
        </welcome-file-list>
    
    </web-app>
    my security-config.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans:beans xmlns:security="http://www.springframework.org/schema/security"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    
        <security:global-method-security pre-post-annotations="enabled">
            <security:expression-handler ref="expressionHandler"/>
        </security:global-method-security>
    
        <security:http auto-config="true" use-expressions="true">
            <security:intercept-url pattern="/**" access="permitAll" />
            <security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
        </security:http>
    
        <beans:bean id="siteminderFilter" class=
    "org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
          <beans:property name="principalRequestHeader" value="SM_USER"/>
          <beans:property name="authenticationManager" ref="authenticationManager" />
        </beans:bean>
    
      <beans:bean id="expressionHandler"
          class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
            <beans:property name="permissionEvaluator" ref="customPermissionEvaluator"/>
      </beans:bean>
      <beans:bean class="com.genks.security.CustomPermissionEvaluator" id="customPermissionEvaluator"/>
      
      <beans:bean id="preauthAuthProvider"
    class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <beans:property name="preAuthenticatedUserDetailsService">
          <beans:bean id="userDetailsServiceWrapper"
              class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
            <beans:property name="userDetailsService" ref="userDetailsService"/>
          </beans:bean>
        </beans:property>
        </beans:bean>
        
        <security:user-service id="userDetailsService">
            <security:user name="rod" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
            <security:user name="dianne" authorities="ROLE_USER,ROLE_TELLER" />
            <security:user name="scott" authorities="ROLE_USER" />
            <security:user name="peter" authorities="ROLE_USER" />
        </security:user-service>
    
        <security:authentication-manager alias="authenticationManager">
            <security:authentication-provider ref="preauthAuthProvider">
            </security:authentication-provider>
        </security:authentication-manager>
    
    </beans:beans>
    My CustomerPermissionEvaluator
    Code:
    public class CustomPermissionEvaluator implements PermissionEvaluator
    {
        private final DebugLog log = new DebugLog("auth", CustomPermissionEvaluator.class);
        
        /**
         * Evaluates whether the user has permission by delegating to
         * hasPermission(String role, Object permission, Object domain)
         */
        public boolean hasPermission(final Authentication authentication,
                                     final Object targetDomainObject,
                                     final Object permission)
        {
             log.error("hasPermission 1");
             return false;
        }
    
    
        public boolean hasPermission(final Authentication authentication,
                                     final Serializable targetId, 
                                     final String targetType, 
                                     final Object permission)
        {
            log.error("hasPermission 2");
            return false;
        }
    
    }
    My controller:
    Code:
    @Controller
    @RemotingDestination
    @RequestMapping("/auth")
    public class AuthController extends AbstractBaseController
    {
        private final DebugLog log = new DebugLog("auth", AuthController.class);
    
        @RequestMapping(value = "/primitive/StringArray", method = RequestMethod.GET)
        @PreAuthorize("hasRole('ROLE_SUPERVISOR')")
        public @ResponseBody String[] getStringArray()
        {
        	log.error("getStringArray");
        	AuthControllerData yo = new AuthControllerData();
        	Boolean bool = checkAuth("12345");
    
    		return yo.awesomeMethod();
        }
       
        @PreAuthorize("hasPermission(#auth, 'WRITE')")
        private boolean checkAuth(final String auth)
        {
            return (auth.indexOf('1') >= 0);
        }
    }
    And from the logs
    Code:
    2011-05-12 15:21:41.068 MDT,DEBUG,,org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource,main,@org.springframework.security.access.prepost.PreAuthorize(value=hasRole('ROLE_SUPERVISOR')) found on specific method: public java.lang.String[] com.genks.controllers.AuthControllerData.awesomeMethod()
    2011-05-12 15:21:41.101 MDT,DEBUG,,org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource,main,Adding security method [CacheKey[com.genks.controllers.AuthControllerData; public java.lang.String[] com.genks.controllers.AuthControllerData.awesomeMethod()]] with attributes [[authorize: 'hasRole('ROLE_SUPERVISOR')', filter: 'null', filterTarget: 'null']]
    2011-05-12 15:21:41.205 MDT,INFO ,,org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor,main,Validated configuration attributes
    2011-05-12 15:21:41.462 MDT,DEBUG,,org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource,main,@org.springframework.security.access.prepost.PreAuthorize(value=hasRole('ROLE_SUPERVISOR')) found on specific method: public java.lang.String[] com.genks.controllers.AuthControllerData.getStringArray()
    2011-05-12 15:21:41.463 MDT,DEBUG,,org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource,main,Adding security method [CacheKey[com.genks.controllers.AuthControllerData; public java.lang.String[] com.genks.controllers.AuthControllerData.getStringArray()]] with attributes [[authorize: 'hasRole('ROLE_SUPERVISOR')', filter: 'null', filterTarget: 'null']]

  • #2
    You're call to checkAuth is an internal method call within the same class, so it won't pass through the security interceptor if you are using Spring AOP. You would need to useAspectJ interception to intercept internal method calls.

    Comment


    • #3
      Thanks for the reply Luke.

      Soon after posting this, I noticed the "private" and changed it to public but could not edit the post. Even with checkAuth() public the customPermEval still doesn't get called. Even the public getStringArray()'s PreAuthorize annotation doesn't seem to do anything either.

      Comment


      • #4
        It doesn't matter whether it is private or public. The call is still made internally within the object so will not be intercepted using Spring AOP.

        Comment


        • #5
          Originally posted by Luke Taylor View Post
          It doesn't matter whether it is private or public. The call is still made internally within the object so will not be intercepted using Spring AOP.
          Oh, I see. Didn't realize that.

          Is getStringArray() suffering the same problem, or should its @PreAuthorize work?

          Comment


          • #6
            If it is called through a reference to the AOP proxy, then no. When the checkAuth() method is called from getStringArray() then it is not made via a reference to the AOP proxy, but directly on the object itself.

            This is a common misconception. I'd suggest a read of the Spring AOP documentation.

            Comment

            Working...
            X