Announcement Announcement Module
Collapse
No announcement yet.
Issues with permitAll and no anonymous user Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Issues with permitAll and no anonymous user

    I would have expected the following to yield the same results:

    Code:
    <sec:http pattern="/whatever*/**">
    </sec:http>
    
    <sec:http use-expressions="true">
         <sec:intercept-url pattern="/**" access="isAuthenticated()" />
    </sec:http>
    and

    Code:
    <sec:http use-expressions="true">
         <sec:intercept-url pattern="/whatever*/**" access="permitAll" />
         <sec:intercept-url pattern="/**" access="isAuthenticated()" />
    </sec:http>
    However, they don't appear to operate in the same way. The first configuration allows users hitting /whatever right through. The second throws a CredentialsNotFoundException. The reason for this occurring is that in AbstractSecurityInterceptor.beforeInvocation(Objec t object), in the first case, there are no attributes, so the check goes into
    Code:
    if (attributes == null || attributes.isEmpty())
    and returns null. However, in the second example, there is an attribute - "permitAll" to it does not enter that if, continues on, and since there is no authentication throws a CredentialsNotFoundException. However, if I add an anonymous element, as follows, then there is an authentication and it succeeds.


    Code:
    <sec:http>
         <sec:intercept-url pattern="/whatever*/**" access="permitAll" />
         <sec:intercept-url pattern="/**" access="isAuthenticated()" />
         <sec:anonymous />
    </sec:http>
    I am just wondering if this is as expected, and if you should have to specify the anonymous element in order for this to work? In code, where it checks if there are attributes, it could of course also check if the attribute is permitAll and circumvent the authentication check, but I am wondering if it works the way it does for historical purposes, or what the reasoning is behind it. I would just like to understand it better, or know if there is an issue with it.

    One more thing of note - we have customized some things in our use of Spring Security, so there is a chance that we have broken things somewhere, but I am thinking that this would still be valid in a non-customized environment (although bringing it up because I could be wrong).

    Thanks, Matt
    Last edited by [email protected]; Nov 16th, 2012, 03:44 PM.

  • #2
    For starters your expression is wrong it should be permitAll(). Also there is a difference (you should also set security="none" if you use multiple http elements) as in the first no filters get executed and in the second filters get executed so there is a difference in the request handling.

    Also /whatever doesn't match /whatever*/** (if I read correctly)...

    Comment


    • #3
      Thank you for the feedback, although I am going to have to disagree on these points, or at least say that none of the points would affect what I am asking.

      If I recall, both permitAll and permitAll() work exactly the same, although I have not tried permitAll() for a long time. However, we are literally using permitAll in hundreds of applications, so if it really is wrong for some reason please let me know. Additionally, the documentation would point to permitAll without the parenthesis as the correct way - unless I am reading it wrong - http://static.springsource.org/sprin...el-access.html. Either way, I can assure you that it is not the root of this problem. It could be part of the problem if the code that I referenced was checking for permitAll and not taking into account the use of parenthesis or not, but it is not checking the individual attributes at all, just whether or not any exist - until it gets to the decision voters, which is well past when this issue occurs.

      With regard to security="none", I understand the filter vs. non-filter concept fully, but disagree that you should always use security="none" if you have more than one http element. Say for instance you would like to secure part of your application with basic auth (maybe a webservice portion of the application), and another part with form auth. In that case, you want both http elements to go through the security filters. This concept is alluded to in this Spring Security webcast put out by Rob Winch - http://www.springsource.org/node/3670. I do understand that my first http element is empty which is possibly why you are recommending security="none", but I have it like that to illustrate the point. Both go into the security filter, and act in different ways, when I would expect them to act the same. The point is if I changed:

      Code:
      <sec:http pattern="/whatever*/**">
      </sec:http>
      to
      Code:
      <sec:http pattern="/whatever*/**" use-expressions="true">
      	<sec:intercept-url pattern="/whatever" access="permitAll" />
      </sec:http>
      without adding the anonymous user element in the second example, the first would "work", and the second would fail with a CredentialsNotFound exception. Why? Is that expected? Both go through the security filter and act in different ways although I think the second should behave as the first and allow the user through without specifying an anonymous user (as in <sec: anonymous>). But if there is a reason for this, I am asking to be enlightened.

      With regard to /whatever*/** matching /whatever, I am not sure what to say. It matches /whatever and more so it should not influence this question. However, if it is a hangup or incorrect in some way, replace /whatever*/** with /whatever throughout my examples, and my question is still the same.

      Thanks, Matt

      Comment


      • #4
        Thank you for the feedback, although I am going to have to disagree on these points, or at least say that none of the points would affect what I am asking.

        If I recall, both permitAll and permitAll() work exactly the same, although I have not tried permitAll() for a long time. However, we are literally using permitAll in hundreds of applications, so if it really is wrong for some reason please let me know. Additionally, the documentation would point to permitAll without the parenthesis as the correct way - unless I am reading it wrong - http://static.springsource.org/sprin...el-access.html. Either way, I can assure you that it is not the root of this problem. It could be part of the problem if the code that I referenced was checking for permitAll and not taking into account the use of parenthesis or not, but it is not checking the individual attributes at all, just whether or not any exist - until it gets to the decision voters, which is well past when this issue occurs.

        With regard to security="none", I understand the filter vs. non-filter concept fully, but disagree that you should always use security="none" if you have more than one http element. Say for instance you would like to secure part of your application with basic auth (maybe a webservice portion of the application), and another part with form auth. In that case, you want both http elements to go through the security filters. This concept is alluded to in this Spring Security webcast put out by Rob Winch - http://www.springsource.org/node/3670. I do understand that my first http element is empty which is possibly why you are recommending security="none", but I have it like that to illustrate the point. Both go into the security filter, and act in different ways, when I would expect them to act the same. The point is if I changed:

        Code:
        <sec:http pattern="/whatever*/**">
        </sec:http>
        to
        Code:
        <sec:http pattern="/whatever*/**" use-expressions="true">
        	<sec:intercept-url pattern="/whatever" access="permitAll" />
        </sec:http>
        without adding the anonymous user element in the second example, the first would "work", and the second would fail with a CredentialsNotFound exception. Why? Is that expected? Both go through the security filter and act in different ways although I think the second should behave as the first and allow the user through without specifying an anonymous user (as in <sec: anonymous>). But if there is a reason for this, I am asking to be enlightened.

        With regard to /whatever*/** matching /whatever, I am not sure what to say. It matches /whatever and more so it should not influence this question. However, if it is a hangup or incorrect in some way, replace /whatever*/** with /whatever throughout my examples, and my question is still the same.

        Thanks, Matt

        Comment


        • #5
          With regard to security="none", I understand the filter vs. non-filter concept fully, but disagree that you should always use security="none" if you have more than one http element.
          You are right which is basically what I meant but failed to express, you should set none if you don't want security. However I have to say that if you still want the SecurityContext to be populated you need the filters (permitAll is indeed something else as no security).

          If I recall, both permitAll and permitAll() work exactly the same, although I have not tried permitAll() for a long time
          You are using expressions and I like to be consistent but that is probaly just me (personal preference). I still associate expressions without ([optional args]) to be no expression (probably due to the fact that I go back to Acegi Security since its inception and that didn't have expression).

          There is still a difference in the way the 2 requests are handled and that is why it isn't working as you expect. Due to the fact that you have defined a secure resource it is expected that there is an Authentication object. You defined it as a secured object and permitAll basically means anyone with authentication can access it (which is why it works with Anonymous).

          The part with 2 elements no check is executed as it isn't defined as a secured resource and as such the rule above doesn't apply.

          If you want a resource to be accessible for anyone simply don't define an intercept-url, all the other filters will still be applied.


          I am just wondering if this is as expected, and if you should have to specify the anonymous element in order for this to work? In code, where it checks if there are attributes, it could of course also check if the attribute is permitAll and circumvent the authentication check, but I am wondering if it works the way it does for historical purposes, or what the reasoning is behind it. I would just like to understand it better, or know if there is an issue with it.
          Basically it comes down to this if you define something as a secured resource it is expected that there is an authentication object. PermitAll means permit anyone who has an authentication object.

          Your suggested workaround wouldn't work as it is an expression and it could be permitAll with some additional requirements (far fetched maybe but I have seen stranger things ).

          Comment

          Working...
          X