First off I have googled this extensively and while it appears that there is supposedly a fix in place I cannot successfully reference an injected @Bean
inside of a PermissionEvaluator
:
https://jira.springsource.org/browse/SEC-2136?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
In that issue's comments section Rob Winch provides a work around suggestion
to work around this issue, you can proxy your permissionEvaluator using LazyInitTargetSource
That being said, I am having trouble implementing the annotation-based JavaConfig version of the posted XML. I am using Spring Boot 1.0.0.BUILD-SNAPSHOT and spring-boot-starter-security.
I have a class to configure method security as follows:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new MyPermissionEvaluator());
expressionHandler.setParameterNameDiscoverer(new SimpleParameterDiscoverer());
return expressionHandler;
}
}
And the start of a PermissionEvaluator
:
public class MyPermissionEvaluator implements PermissionEvaluator {
private static final Logger LOG = LoggerFactory.getLogger(MyPermissionEvaluator.class);
@Autowired
private UserRepository userRepo;
@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
if (authentication == null || !authentication.isAuthenticated()) {
return false;
}
if (permission instanceof String) {
switch((String) permission) {
case "findUser":
return handleUserPermission(authentication, targetDomainObject);
default:
LOG.error("No permission handler found for permission: " + permission);
}
}
return false;
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
throw new RuntimeException("Id-based permission evaluation not currently supported.");
}
private boolean handleUserPermission(Authentication auth, Object targetDomainObject) {
if (targetDomainObject instanceof Long) {
boolean hasPermission = userRepo.canFind((Long) targetDomainObject);
return hasPermission;
}
return false;
}
}
What needs to be done so that I can get a reference to my UserRepository
from inside the PremissionEvaluator
? I've attempted various workarounds w/ no success. It seems that nothing can be @Autowired
into the PermissionEvaluator
...
Nothing can be autowired into an object that is created with new ...()
(unless you are using @Configurable
and AspectJ). So you almost certainly need to pull your PermissionEvaluator
out into a @Bean
. If you need to make it a lazy proxy as well (because of the ordering sensitivity of Spring Security initialization), then you should add @Lazy @Scope(proxyMode=INTERFACES)
(or TARGET_CLASS
if that suits you better).
I had the same issue and the answer from Dave Syer worked perfectly for me. To respond to the comment from jasonfungsing, to pull the PermissionEvaluator into a Bean I annotated my custom class with @Component and @Autowired the DAO into it:
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator{
private CustomRepository customRepository;
@Autowired
public void setCustomRepository(CustomRepository customRepository) {
this.customRepository = customRepository;
}
@Override
public boolean hasPermission(Authentication authentication, Object target, Object permission) {
if (target instanceof ...
Then in my GlobalMethodSecurityConfiguration overriding class I created a private instance variable of my PermissionEvaluator class, @Autowired the PermissionEvaluator into it and used this instance in my setPermissionEvaluator method call (thus avoiding a "new" call):
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{
private DataSource datasource;
private CustomPermissionEvaluator customPermissionEvaluator;
@Autowired
public void setCustomPermissionEvaluator(CustomPermissionEvaluator customPermissionEvaluator) {
this.customPermissionEvaluator = customPermissionEvaluator;
}
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(customPermissionEvaluator);
return expressionHandler;
}
I did not need to use the @LAZY or @SCOPE annotations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With