Announcement Announcement Module
Collapse
No announcement yet.
intercept-url order being violated? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • intercept-url order being violated?

    Hi,

    I an trying to use spring security to direct URLs to a secure channel based upon pattern matching. I am using a ChannelProcessingFilter, with spring namespace configuration to define various the various intercept-url values.

    It might be best to provide an illustration at this point:
    Code:
      <bean id="ChannelFilter"
       class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
        <property name="channelDecisionManager" ref="channelDecisionManager" />
        <property name="securityMetadataSource">
          <security:filter-invocation-definition-source
            path-type="ant">
    
             <!-- We don't care about this one -->
             <security:intercept-url pattern="/objects/*/foo*"
              access="REQUIRES_SECURE_CHANNEL" />
    
            <!-- This url should be secure -->
            <security:intercept-url pattern="/objects/*/validate*"
              access="REQUIRES_SECURE_CHANNEL" />
    
            <!-- These don't have to be secure -->
            <security:intercept-url pattern="/objects*/**"
              method="GET" access="ANY_CHANNEL" />
    
          </security:filter-invocation-definition-source>
        </property>
      </bean>
    It looks like these patterns are being initialized correctly when spring initializes:
    Code:
    DEBUG 2011-04-02 14:22:59.469 [main] (DefaultFilterInvocationSecurityMetadataSource) Added URL pattern: /objects/*/foo*; attributes: [REQUIRES_SECURE_CHANNEL]
    DEBUG 2011-04-02 14:22:59.469 [main] (DefaultFilterInvocationSecurityMetadataSource) Added URL pattern: /objects/*/validate*; attributes: [REQUIRES_SECURE_CHANNEL]
    DEBUG 2011-04-02 14:22:59.469 [main] (DefaultFilterInvocationSecurityMetadataSource) Added URL pattern: /objects*/**; attributes: [ANY_CHANNEL] for HTTP method 'GET'
    My problem is that if I submit a GET for a url that should match the middle "validate" pattern, ONLY the last pattern is tested at all (and of course, it matches). I deduce this from the debug log:
    Code:
    DEBUG 2011-04-02 13:47:22.785 [http-8080-1] (DefaultFilterInvocationSecurityMetadataSource) Converted URL to lowercase, from: '/objects/fedora-system:fedoraobject-3.0/validate'; to: '/objects/fedora-system:fedoraobject-3.0/validate'
    DEBUG 2011-04-02 13:47:22.785 [http-8080-1] (DefaultFilterInvocationSecurityMetadataSource) Candidate is: '/objects/fedora-system:fedoraobject-3.0/validate'; pattern is /objects*/**; matched=true
    DEBUG 2011-04-02 13:47:22.786 [http-8080-1] (ChannelProcessingFilter) Request: FilterInvocation: URL: /objects/fedora-system:FedoraObject-3.0/validate; ConfigAttributes: [ANY_CHANNEL]
    As you can see, it only tests the url against the *last* pattern, not the other two. If I remove that last intercept-url, spring now correctly evaluates the two that were before it, in the order in which they appear in the file:
    Code:
    DEBUG 2011-04-02 14:27:22.727 [http-8080-1] (DefaultFilterInvocationSecurityMetadataSource) Converted URL to lowercase, from: '/objects/fedora-system:fedoraobject-3.0/validate'; to: '/objects/fedora-system:fedoraobject-3.0/validate'
    DEBUG 2011-04-02 14:27:22.727 [http-8080-1] (DefaultFilterInvocationSecurityMetadataSource) Candidate is: '/objects/fedora-system:fedoraobject-3.0/validate'; pattern is /objects/*/foo*; matched=false
    DEBUG 2011-04-02 14:27:22.727 [http-8080-1] (DefaultFilterInvocationSecurityMetadataSource) Candidate is: '/objects/fedora-system:fedoraobject-3.0/validate'; pattern is /objects/*/validate*; matched=true
    DEBUG 2011-04-02 14:27:22.727 [http-8080-1] (ChannelProcessingFilter) Request: FilterInvocation: URL: /objects/fedora-system:FedoraObject-3.0/validate; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
    Just for clarity, the configuration xml is exactly the same as the above, only without that last intercept url:
    Code:
      <bean id="ChannelFilter"
       class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
        <property name="channelDecisionManager" ref="channelDecisionManager" />
        <property name="securityMetadataSource">
          <security:filter-invocation-definition-source
            path-type="ant">
    
             <!-- We don't care about this one -->
             <security:intercept-url pattern="/objects/*/foo*"
              access="REQUIRES_SECURE_CHANNEL" />
    
            <!-- This url should be secure -->
            <security:intercept-url pattern="/objects/*/validate*"
              access="REQUIRES_SECURE_CHANNEL" />
    
          </security:filter-invocation-definition-source>
        </property>
      </bean>
    The documentation seems to be very explicit that these patterns are evaluated strictly in the order in which they are defined, and evaluation stops once a pattern matches. Therefore, it is recommended to place the most specific matches first. My experience tends to make me believe that this is not happening, and the actual matching order is undefined (or follows some set of rules that is not apparent). Could this be a bug, or is there something important I am missing?

    edit: This is spring 3.0.3 release
    Last edited by birkie; Apr 2nd, 2011, 01:45 PM. Reason: add spring version

  • #2
    After some experimentation, I think i have figured out the logic Spring is actually applying:
    • All intercept patterns with an explicitly declared method (e.g. method="GET") will be evaluated first (in order) for a request which matches the method
    • If no patterns explicitly bound to the current method have matched, then all the patterns without a declared method will be applied, in order.

    So, If I have:
    Code:
      <bean id="ChannelFilter"
        class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
        <property name="channelDecisionManager" ref="channelDecisionManager" />
        <property name="securityMetadataSource">
          <security:filter-invocation-definition-source
            path-type="ant">
    
            <security:intercept-url pattern="/objects/*/foo*"
              method="GET" access="REQUIRES_SECURE_CHANNEL" />
            <security:intercept-url pattern="/objects/*/validate*"
              access="REQUIRES_SECURE_CHANNEL" />
            <security:intercept-url pattern="/objects*/x/**"
              method="GET" access="ANY_CHANNEL" />
             
          </security:filter-invocation-definition-source>
        </property>
      </bean>
    .. and issue a GET request for a resource that matches pattern #2, the intercepts will be processed in the order 1-3-2. The debug logs confirm that.

    Comment


    • #3
      You are correct. In 3.0.x, method-specific matches take precedence over those without a method. The class in question is DefaultFilterInvocationSecurityMetadataSource.

      In 3.1, the behaviour is more logical since all the matching logic is encapsulated within the RequestMatcher interface, resulting in strict ordering.

      Comment

      Working...
      X