Announcement Announcement Module
Collapse
No announcement yet.
hasPermission on generics? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • hasPermission on generics?

    I'm trying to secure a call like this:
    Code:
    <T extends ModelObject> T getEntity(@NotNull Class<T> entity, @NotNull Serializable id);
    Since this code doesn't work as Spring is trying to call inexistant 'hasPermission(Authentication, Serializable, Class, Object)
    Code:
    @PreAuthorize("hasPermission(#id, #entity, read)")
    <T extends ModelObject> T getEntity(@NotNull Class<T> entity, @NotNull Serializable id);
    this could work:
    Code:
    @PreAuthorize("hasPermission(#id, #entity.getCanonicalName(), read)")
    <T extends ModelObject> T getEntity(@NotNull Class<T> entity, @NotNull Serializable id);
    but I get a:
    Code:
    org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 0): Method call: Method getCanonicalName() cannot be found on com.company.common.model.member.Member type
    suggesting the method call is made on the 'T' instead of the Class type itself.

    I can't find anything on hasPermission and generics either on the forum or on the web.
    I'm a newbie in SPel (Acl as well indeed) so any suggestion might help!

  • #2
    This doesn't really have anything to do with generic usage. It is actually to do with the usage of Class. You are running into SPR-9017 which is a bug in the SpEL language. Although not ideal, you can work around this using a utility class as shown below:

    Code:
    public class SpelUtil {
        public static String name(Class clazz) {
            return clazz == null ? null : clazz.getName();
        }
    }
    Then update your annotations to:

    Code:
    @PreAuthorize("hasPermission(#id, T(SpelUtil).name(#entity), read)")
    Out of curiosity is there a reason you are using @PreAuthorize on this? It seems like you would also be able to use @PostAuthorize and refer to the returnObject. Yes you suffer from a lookup of the object, but perhaps that is the lesser of evils (especially if you use information on that object to determine if the user is authorized).
    Last edited by Rob Winch; Aug 21st, 2012, 08:17 PM.

    Comment


    • #3
      Intuitively @PreAuthorize made more sense to me, mainly to save the object lookup I guess. I did not even consider @Post before.

      The doc indeed specifies "Less commonly, you may wish to perform an access-control check after the method has been invoked. This can be achieved using the @PostAuthorize annotation. To access the return value from a method, use the built–in name returnObject in the expression." which probably made me forget about it!

      But now that you mention it, it just works and can indeed be useful in some cases where info on the returned object have to be used.

      And it's a welcome alternative as still I can't make head or tails of SpEL for now, my IDE doesn't seem to let me debug further down ExpressionUtils.evaluateAsBoolean(...). That's where I can lookup SpelEvaluationException.

      Code:
      @PreAuthorize("hasPermission(#id, T(SpelUtil).name(#entity), read)")
      doesn't seem to work, I get a
      Code:
      org.springframework.expression.spel.SpelEvaluationException: EL1005E:(pos 0): Type cannot be found 'SpelUtil'
      Since
      Code:
      @PreAuthorize("hasPermission(#id, #entity.getCanonicalName(), read)")
      <T extends ModelObject> T getEntity(@NotNull Class<T> entity, @NotNull Serializable id);
      produced
      Code:
      org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 0): Method call: Method getCanonicalName() cannot be found on com.company.common.model.member.Member type
      I've tried
      Code:
      @PreAuthorize("hasPermission(#id, #entity.getClass().getCanonicalName(), read)")
      which worked but evaluated the targetType as 'java.lang.Class'. This seems quite inconsistent to me.

      Anyways, I'd be very interested in getting 'T(SpelUtil).name(#entity)' to be evaluated successfully.

      I thing it'd be a good idea to include in the doc a syntax example to work with generics.

      Comment


      • #4
        Originally posted by Jean View Post
        Code:
        @PreAuthorize("hasPermission(#id, T(SpelUtil).name(#entity), read)")
        doesn't seem to work, I get a
        Code:
        org.springframework.expression.spel.SpelEvaluationException: EL1005E:(pos 0): Type cannot be found 'SpelUtil'
        You need to write the utility class I posted and include it in your source code. Spring does not provide the utility as it is a workaround for the bug previously mentioned.

        Originally posted by Jean View Post
        I thing it'd be a good idea to include in the doc a syntax example to work with generics.
        The syntax does not vary for working with generics so it should not matter. Also, as mentioned previously this issue is not related to working with generics it is related to invoking methods on Class per the bug I linked to.

        PS: I would consider voting on the issue and/or watching it so you can encourage it to be fixed and find out when it is fixed.

        Comment

        Working...
        X