Michael Scharhag

About Michael Scharhag

Michael Scharhag is a Java Developer, Blogger and technology enthusiast. Particularly interested in Java related technologies including Java EE, Spring, Groovy and Grails.

Grails: Calling bean methods in Spring Security expressions

Some days ago while working on a Grails application I was in a situation where a wanted to call a bean method from a Spring security SPEL expression. I was using the @PreAuthorize annotation from the Spring Security ACL plugin and wanted to do something like this:
 
 
 
 
 
 
 

@PreAuthorize("myService.canAccessUserProfile(#profileId)")
public Profile getUserProfile(long profileId) {
  ...
}

@PreAuthorize takes a SPEL expression as parameter that is evaluated to see if the currently logged in user is allowed to access the getUserProfile() method. Within this SPEL expression I wanted to call the canAccessUserProfile() method of myService for performing the security check. In the following I will explain which steps are necessary to make this working.

Luckily it is possible to reference beans from SPEL expressions by prefixing their name with an @ symbol:

@PreAuthorize("@myService.canAccessUserProfile(#profileId)")

However, this change alone won’t work out of the box and we have to do some small adjustments on the Spring Security configuration.

The SPEL expression parser (see: SpelExpressionParser) that is used to parse the security expression delegates the lookup of beans to a BeanResolver. In order to make the security expression from above work we have to create a BeanResolver implementation and add it to the Spring Security configuration.

Creating a BeanResolver for Grails is very simple:

class GrailsBeanResolver implements BeanResolver {

  GrailsApplication grailsApplication

  @Override
  public Object resolve(EvaluationContext evaluationContext, String beanName) throws AccessException {
    return grailsApplication.mainContext.getBean(beanName)
  }
}

We only have to implement the resolve() method to satisfy the BeanResolver interface. In our example we delegate this job to the bean factory of our Grails application. So, we can access all available beans within security expressions.

Now we have to add our bean resolver to the SPEL evaluation context (see: EvaluationContext). This can be done by overriding the createEvaluationContext() of Spring Securities DefaultMethodSecurityExpressionHandler:

class GrailsExpressionHandler extends DefaultMethodSecurityExpressionHandler {

  BeanResolver beanResolver

  @Override
  public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation method) {
    StandardEvaluationContext context = (StandardEvaluationContext) super.createEvaluationContext(auth, method)
    context.setBeanResolver(beanResolver)
    return context;
  }
}

As the name suggests createEvaluationContext() is responsible for creating the evaluation context for security expressions. The only thing we do is adding a beanResovler after the EvaluationContext has been created.

After that, we have to configure our two new beans in grails-app/conf/spring/resources.groovy using the Spring Bean DSL:

beans = {
  expressionHandler(GrailsExpressionHandler) {
    beanResolver              = ref('beanResolver')
    parameterNameDiscoverer   = ref('parameterNameDiscoverer')
    permissionEvaluator       = ref('permissionEvaluator')
    roleHierarchy             = ref('roleHierarchy')
    trustResolver             = ref('authenticationTrustResolver')  
  }

  beanResolver(GrailsBeanResolver) {
    grailsApplication = ref('grailsApplication')
  }
}

Normally the expressionHandler bean would be an instance of DefaultMethodSecurityExpressionHandler as mentioned above. Since we want Spring Security to use our GrailsExpressionHandler we have to override the expressionHandler bean. The only new dependency we added is the beanResolver property. The other four dependencies of expressionHandler are required by DefaultMethodSecurityExpressionHandler (the base class of GrailsExpressionHandler). These dependencies are already provided by the Spring Security plugins.

Now it should be possible to reference beans using the @ prefix and call their methods in security expressions.
 

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

Leave a Reply


nine − 6 =



Java Code Geeks and all content copyright © 2010-2015, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

Get ready to Rock!
To download the books, please verify your email address by following the instructions found on the email we just sent you.

THANK YOU!

Close