Reputation: 29
I want to pass SecurityExpressionRoot
class, which i can access inside @PreAuthorise()
annotation, to my custom checkAccess()
method which checks access to specific method, using some logic based on authorities, roles and a additional variables that i pass to this method.
Inside @PreAuthorise()
I can access methods from SecurityExpressionRoot
, for example. hasAuthority()
Is there any way to do that?
Controller:
public class TestController {
private final PreAuthorizeChecker preAuthorizeChecker;
@Autowired
public TestController(PreAuthorizeChecker preAuthorizeChecker) {
this.preAuthorizeChecker = preAuthorizeChecker;
}
@GetMapping(path = "/test")
@PreAuthorize("@preAuthorizeChecker.checkAccess(/*SecurityExpressionRoot.getSomehow()*/)") //How to obtain SecurityExpressionRoot instance?
public ResponseEntity<Void> get() {
return;
}
PreAuthorizeChecker:
@Component
public class PreAuthorizeChecker {
@Autowired
public PreAuthorizeChecker() {
}
public boolean checkAccess(SecurityExpressionRoot securityExpressionRoot) {
//do sth with securityExpressionRoot
return true;
}
}
Upvotes: 0
Views: 2780
Reputation: 1571
You might find that part 5 of this blog, A Custom Security Expression with Spring Security, on Baelding.com helpful. The author suggests extending SecurityExpressionRoot and adding your custom method to the new class like this:
public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
public CustomMethodSecurityExpressionRoot(Authentication authentication) {
super(authentication);
}
public boolean checkAccess() {
//do sth with securityExpressionRoot
return true;
}
...
}
Then you will need to inject that new class into the expression handler like this:
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(this.trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
return root;
}
}
Finally, you just need to create the expression handler in your security config like this:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
CustomMethodSecurityExpressionHandler expressionHandler = new CustomMethodSecurityExpressionHandler();
return expressionHandler;
}
}
Then your new expression should be available:
@PreAuthorize("checkAccess()")
public ResponseEntity<Void> get() {
return;
}
Upvotes: 1