Creating custom PostAuthorize method in Spring Security
authorization, java, spring, spring-security
Solution
It seems you are on an older version of Spring Security. As of Spring Security 3.1.5+ SEC-2245 is fixed & you can create your own expression root and implement MethodSecurityExpressionOperations.
Problem
I am trying to create a a custom method for use in Pre/Post Authorize calls like this: ``` public class CustomLSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler{ public CustomSecurityExpressionHandler(){ super(); } @Override protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation){ CustomSecurityExpressionRoot root = new CustomSecurityExpressionRoot(authentication); root.setThis(invocation.getThis()); root.setPermissionEvaluator(getPermissionEvaluator()); return root; } } ``` and ``` public class CustomSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations { private Object filterObject; private Object returnObject; private Object target; public CustomSecurityExpressionRoot(Authentication a) { super(a); } public boolean testDecision(String test){ System.out.println("Printing:"+test+"\n"); return true; } public void setFilterObject(Object filterObject) { this.filterObject = filterObject; } public Object getFilterObject() { return filterObject; } public void setReturnObject(Object returnObject) { this.returnObject = returnObject; } public Object getReturnObject() { return returnObject; } void setThis(Object target) { this.target = target; } public Object getThis() { return target; } public boolean hasPermission(Object permission) { try { return super.hasPermission(null, null, permission); } catch (AccessDeniedException e) { return false; } } public boolean checkPermission(Object permission) { return super.hasPermission(null, null, permission); } @Override public boolean hasPermission(Object targetId, String targetType, Object permission) { try { return super.hasPermission(targetId, targetType, permission); } catch (AccessDeniedException e) { return false; } } public boolean checkPermission(Object targetId, String targetType, Object permission) { return super.hasPermission(targetId, targetType, permission); } @Override public boolean hasPermission(Object target, Object permission) { try { return super.hasPermission(target, permission); } catch (AccessDeniedException e) { return false; } } public boolean checkPermission(Object target, Object permission) { return super.hasPermission(target, permission); } } ``` As seen above I have added the new method testDecision(String), which I can successfully use in my preAuthorize call as below: ``` @PreAuthorize("testDecision('TestString')") Event getEvent(int eventId); ``` But when I call it in the context of a PostAuthorize as: ``` @PostAuthorize("testDecision('TestString')") Event getEvent(int eventId); ``` I get a ClassCastException: ``` SEVERE: Servlet.service() for servlet [Spring MVC Dispatcher Servlet] in context with path [/myapp] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: com.example.CustomSecurityExpressionRoot cannot be cast to org.springframework.security.access.expression.method.MethodSecurityExpressionRoot] with root cause java.lang.ClassCastException: com.example.CustomSecurityExpressionRoot cannot be cast to org.springframework.security.access.expression.method.MethodSecurityExpressionRoot at org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler.setReturnObject(DefaultMethodSecurityExpressionHandler.java:156) at org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice.after(ExpressionBasedPostInvocationAdvice.java:49) at org.springframework.security.access.prepost.PostInvocationAdviceProvider.decide(PostInvocationAdviceProvider.java:38) at org.springframework.security.access.intercept.AfterInvocationProviderManager.decide(AfterInvocationProviderManager.java:73) at org.springframework.security.access.intercept.AbstractSecurityInterceptor.afterInvocation(AbstractSecurityInterceptor.java:282) at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:68) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at com.sun.proxy.$Proxy15.getEvent(Unknown Source) (..truncated..) ``` Anyone can help me figure out what I am doing wrong?