views:

78

answers:

1

I'm developing a Grails (Version 1.3.3) Web-Application using the Grails Spring-Security Plugin, Spring-Security-Core-1.0.1 (which, in turn, uses spring-security-3.0.2.RELEASE).

I would like to provide Spring-Security annotation-based access control on actions within a controller.

I have been able to successfully do basic authentication using the following annotations:

@Secured("hasAnyRole('ROLE_USER')")
def list = {
...  
}

This works - providing access to the list action/view only to those with the ROLE_USER role.

However, the set of which roles are allowed to perform certain controller-actions may change over time and is a function of the system's overall state. That is, the set of roles allowed to perform a given action might be returned by a service or domain-object method.

One way I might be able to do something like this would be to use Spring-Security's "Expression Based Access Control" (@Pre and @Post annotations), something like the example at the Spring Security Documentation:

 @PreAuthorize("hasPermission(#contact, 'admin')")
 public void deletePermission(Contact contact, Sid recipient, Permission permission);

In this example for access control decisions, one can gain access to the objects sent to the method (eg contact) using the #contact syntax.

However, I can't get @PreAuthorize (or @RolesAllowed) annotations to work on a Grails controller-action. If I annotate the list action with @PreAuthorize (rather than @Secured, as above), I get the following error:

Annotation @org.springframework.security.access.prepost.PreAuthorize is not allowed on element FIELD

This isn't surprising -- the action is a Groovy closure (a field with executable code), rather than a method. However, I've also tried using the annotation on methods, called from the closure, like:

  def list = {
    testMethod()
    ....
  }

@PreAuthorize("hasRole('ROLE_USER')")
  public boolean testMethod(){
    println "testMethod succeess"
    return true;
  }

While this doesn't throw any errors, it also doesn't appear to provide any access control. ("testMethod success" is printed whether or not the user has ROLE_USER).

So, I've tried a few different things (and read the documentation), but haven't been able to work out a nice way of using @PreAuthorize annotations with a Grails controller-action. Is this possible? Is there a better way in a Grails app to use Spring-Security-Annotations to provide access-control that is a function of the state of the system?

+2  A: 

You need to use the ACL plugin to use those annotations, but they won't work on controller actions for the reasons you point out. @Secured works because I created a copy of the Spring Security annotation that allows it to be placed on fields as well as methods and classes, and I look for them and wire them up explicitly. You'll need to use annotated services that you call from your controllers.

Burt Beckwith