Skip to content

Instantly share code, notes, and snippets.

@matteocedroni
Last active September 20, 2023 00:47
Show Gist options
  • Save matteocedroni/b0e5a935127316603dfb to your computer and use it in GitHub Desktop.
Save matteocedroni/b0e5a935127316603dfb to your computer and use it in GitHub Desktop.
Programmatically check Spring Security expressions

Spring Security checker

Security checker is a programmatically way for evaluating Spring Security expressions, normally evaluated by @PreAuthorize annotation (a SpEL-enabled equivalent to @Secured annotation).

The annotation way applies only to certain Spring enabled beans, but in some case your project may need to evaluate the same kind of expressions elsewhere in the code.

##Usage Enable global method security:

<security:global-method-security pre-post-annotations="enabled" />

Simply pass standard or SpEL security expression to check method. For example:

SecurityChecker.check("hasRole('ROLE_USER')");

A complete reference can be found here

import org.apache.log4j.Logger;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.security.access.expression.ExpressionUtils;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.util.SimpleMethodInvocation;
import java.lang.reflect.Method;
public class SecurityChecker {
static Logger logger = Logger.getLogger(SecurityChecker.class);
private static class SecurityObject{
public void triggerCheck(){ /*NOP*/ }
}
private static Method triggerCheckMethod;
private static SpelExpressionParser parser;
static{
try{ triggerCheckMethod = SecurityObject.class.getMethod("triggerCheck"); }
catch (NoSuchMethodException e) { logger.error(e); }
parser = new SpelExpressionParser();
}
public static boolean check(String securityExpression){
if (logger.isDebugEnabled()) { logger.debug("Checking security expression ["+securityExpression+"]..."); }
SecurityObject securityObject = new SecurityObject();
MethodSecurityExpressionHandler expressionHandler = ContextLoader.getCurrentWebApplicationContext().getBean(DefaultMethodSecurityExpressionHandler.class);
EvaluationContext evaluationContext = expressionHandler.createEvaluationContext(SecurityContextHolder.getContext().getAuthentication(), new SimpleMethodInvocation(securityObject, triggerCheckMethod));
boolean checkResult = ExpressionUtils.evaluateAsBoolean(parser.parseExpression(securityExpression), evaluationContext);
if (logger.isDebugEnabled()){ logger.debug("Check result: "+checkResult); }
return checkResult;
}
}
@ExploreHW
Copy link

Thanks for sharing, this helped a lot.
Just want to add some notes in case of ppl who is using spring boot and spring boot oauth2,
Replace MethodSecurityExpressionHandler expressionHandler = ContextLoader.getCurrentWebApplicationContext().getBean(DefaultMethodSecurityExpressionHandler.class); with
OAuth2MethodSecurityExpressionHandler expressionHandler = new OAuth2MethodSecurityExpressionHandler();
will make it work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment