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.
 

Related Whitepaper:

Java Essential Training

Author David Gassner explores Java SE (Standard Edition), the language used to build mobile apps for Android devices, enterprise server applications, and more!

The course demonstrates how to install both Java and the Eclipse IDE and dives into the particulars of programming. The course also explains the fundamentals of Java, from creating simple variables, assigning values, and declaring methods to working with strings, arrays, and subclasses; reading and writing to text files; and implementing object oriented programming concepts. Exercise files are included with the course.

Get it Now!  

Leave a Reply


1 + = eight



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
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.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books
Get tutored by the Geeks! JCG Academy is a fact... Join Now
Hello. Add your message here.