How to create custom methods for using security expression expressions in spring annotations

I would like to create a class that adds custom methods to use in the spring language a security expression for method-based authorization through annotations.

For example, I would like to create my own method, for example customMethodReturningBoolean, which will be used like this:

@PreAuthorize("customMethodReturningBoolean()") public void myMethodToSecure() { // whatever } 

My question is that. If possible, which class should be a subclass to create my custom methods, how would I decide to configure it in the spring xml configuration files and would anyone come to give me an example of a custom method used this way?

+72
java spring spring-security
Jul 09 2018-11-11T00:
source share
3 answers

You need to subclass two classes.

First install a new method expression handler

 <global-method-security> <expression-handler ref="myMethodSecurityExpressionHandler"/> </global-method-security> 

myMethodSecurityExpressionHandler will be a subclass of myMethodSecurityExpressionHandler , which overrides createEvaluationContext() by setting the MethodSecurityExpressionRoot subclass to MethodSecurityEvaluationContext .

For example:

 @Override public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) { MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer); MethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(auth); root.setTrustResolver(trustResolver); root.setPermissionEvaluator(permissionEvaluator); root.setRoleHierarchy(roleHierarchy); ctx.setRootObject(root); return ctx; } 
+30
Jul 09 2018-11-11T00:
source share

None of the above methods will work anymore. It seems that Spring has come a long way so that users do not redefine SecurityExpressionRoot.

EDIT 11/19/14 Configuring Spring to use security annotations:

 <beans ... xmlns:sec="http://www.springframework.org/schema/security" ... > ... <sec:global-method-security pre-post-annotations="enabled" /> 

Create a bean as follows:

 @Component("mySecurityService") public class MySecurityService { public boolean hasPermission(String key) { return true; } } 

Then do something similar in jsp:

 <sec:authorize access="@mySecurityService.hasPermission('special')"> <input type="button" value="Special Button" /> </sec:authorize> 

Or annotate the method:

 @PreAuthorize("@mySecurityService.hasPermission('special')") public void doSpecialStuff() { ... } 

And remember: if you use Spring, and you need to solve the problem by extending classes, overriding methods, implementing interfaces, etc ... then you are probably doing something wrong. All annotations and xml, so we really love Spring and not (old versions) EJB.

In addition, you can use the Spring Expression Language in your @PreAuthorize annotations to access the current authentication, as well as the method arguments.

For example:

 @Component("mySecurityService") public class MySecurityService { public boolean hasPermission(Authentication authentication, String foo) { ... } } 

Then update your @PreAuthorize to match the new method signature:

 @PreAuthorize("@mySecurityService.hasPermission(authentication, #foo)") public void doSpecialStuff(String foo) { ... } 
+140
Feb 15 '13 at 22:05
source share

Thanks ericacm , but this does not work for several reasons:

  • DefaultMethodSecurityExpressionHandler properties are private (unwanted clicks of visibility)
  • At least in my Eclipse I cannot resolve the MethodSecurityEvaluationContext object

The differences are that we call the existing createEvaluationContext method, and then add our custom root object. Finally, I just returned the object type of StandardEvaluationContext , since the MethodSecurityEvaluationContext method will not be allowed in the compiler (they are both from the same interface). This is the code that I currently have in production.

Make MethodSecurityExpressionHandler use our custom root:

 public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler { // parent constructor public CustomMethodSecurityExpressionHandler() { super(); } /** * Custom override to use {@link CustomSecurityExpressionRoot} * * Uses a {@link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and * configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object. */ @Override public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) { // due to private methods, call original method, then override it root with ours StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi); ctx.setRootObject( new CustomSecurityExpressionRoot(auth) ); return ctx; } } 

This replaces the default root by extending SecurityExpressionRoot . Here I renamed hasRole to hasEntitlement:

 public class CustomSecurityExpressionRoot extends SecurityExpressionRoot { // parent constructor public CustomSecurityExpressionRoot(Authentication a) { super(a); } /** * Pass through to hasRole preserving Entitlement method naming convention * @param expression * @return boolean */ public boolean hasEntitlement(String expression) { return hasRole(expression); } } 

Finally, update securityContext.xml (and make sure it references your applcationContext.xml):

 <!-- setup method level security using annotations --> <security:global-method-security jsr250-annotations="disabled" secured-annotations="disabled" pre-post-annotations="enabled"> <security:expression-handler ref="expressionHandler"/> </security:global-method-security> <!--<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">--> <bean id="expressionHandler" class="com.yourSite.security.CustomMethodSecurityExpressionHandler" /> 

Note. @Secured annotation does not accept this override when passing through another validation handler. So, in the above xml, I turned them off to prevent confusion.

+14
Aug 23 '11 at 19:59
source share



All Articles