java - 自定义 PermissionEvaluation bean 导致循环引用和空指针异常

标签 java spring spring-security

我尝试在 Spring 4 上设置 Spring Security ACL,但遇到空指针异常。

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.acls.jdbc.LookupStrategy]: Circular reference involving containing bean 'webSecurityACL' - consider declaring the factory method as static for independence from its containing instance. Factory method 'lookupStrategy' threw exception; nested exception is java.lang.IllegalArgumentException: DataSource required
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 95 common frames omitted
Caused by: java.lang.IllegalArgumentException: DataSource required
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.security.acls.jdbc.BasicLookupStrategy.<init>(BasicLookupStrategy.java:145)
at com.sample.application.WebSecurityACL.lookupStrategy(WebSecurityACL.java:59)

这是我的 java 配置文件:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityACL extends GlobalMethodSecurityConfiguration {

@Autowired
public DataSource dataSource;

@Bean
EhCacheBasedAclCache aclCache() {
    EhCacheFactoryBean factoryBean = new EhCacheFactoryBean();
    EhCacheManagerFactoryBean cacheManager = new EhCacheManagerFactoryBean();

    factoryBean.setCacheName("aclCache");
    factoryBean.setCacheManager(cacheManager.getObject());
    factoryBean.afterPropertiesSet();

    return new EhCacheBasedAclCache(factoryBean.getObject(), permissionGrantingStrategy(), aclAuthorizationStrategy());
}

@Bean
AclAuthorizationStrategy aclAuthorizationStrategy() {
    return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ACL_ADMIN"));
}

@Bean
PermissionGrantingStrategy permissionGrantingStrategy(){
    return new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
}

@Bean
LookupStrategy lookupStrategy() {
    return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), permissionGrantingStrategy());
}

@Bean
JdbcMutableAclService aclService() {
    JdbcMutableAclService service = new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
    //service.setClassIdentityQuery("select currval(pg_get_serial_sequence('acl_class', 'id'))");
    //service.setSidIdentityQuery("select currval(pg_get_serial_sequence('acl_sid', 'id'))");
    return service;
}

@Bean
PermissionEvaluator permissionEvaluator(){
    return new AclPermissionEvaluator(aclService());
}

@Bean
AclPermissionCacheOptimizer aclPermissionCacheOptimizer(){
    return new AclPermissionCacheOptimizer(aclService());
}

@Override
protected MethodSecurityExpressionHandler createExpressionHandler(){
    DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();

    expressionHandler.setPermissionEvaluator(permissionEvaluator());
    expressionHandler.setPermissionCacheOptimizer(aclPermissionCacheOptimizer());

    return expressionHandler;
}
}

我查明罪魁祸首是permissionEvaluator bean。如果我用 null 替换 aclService() (只是为了测试):

PermissionEvaluator permissionEvaluator(){
    return new AclPermissionEvaluator(null);
}

然后我就可以运行该应用程序了。我无法弄清楚循环引用在哪里。任何建议将不胜感激。

这是我的 gradle 文件:

version '1.0-SNAPSHOT'

apply plugin: 'spring-boot'


buildscript {
repositories {
    mavenCentral()
}
dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.7.RELEASE")
}
}

dependencies {
compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity3:2.1.2.RELEASE")
compile 'org.springframework.security:spring-security-acl:3.2.8.RELEASE'
compile 'net.sf.ehcache:ehcache:2.10.1'
runtime 'mysql:mysql-connector-java:5.1.36'
testCompile group: 'junit', name: 'junit', version: '4.12'
}

最佳答案

原因是数据源没有被注入(inject) -

Caused by: java.lang.IllegalArgumentException: DataSource required at org.springframework.util.Assert.notNull(Assert.java:112) at org.springframework.security.acls.jdbc.BasicLookupStrategy.(BasicLookupStrategy.java:145) at com.sample.application.WebSecurityACL.lookupStrategy(WebSecurityACL.java:59)

你能确认一下吗?您摆脱异常的原因是“AclPermissionEvaluator(null)”也调用数据源,并给出未捕获的异常

关于java - 自定义 PermissionEvaluation bean 导致循环引用和空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34057104/

相关文章:

java - Netbeans:需要在类路径中包含第 3 方目录

java - 记录 Java 中第三方库的使用的标准/官方方法是什么?

java - spring boot - 如何在 HTTP Controller 处理程序中避免 "Failed to instantiate [java.util.List]: Specified class is an interface"?

java - Spring 安全云 : UI service through a ZUUL gateway security setup

grails - 使用grails-spring-security-rest进行基于HTTP基本身份验证 token 的操作

java.lang.RuntimeException : Unable to start activity ComponentInfo{. ..} : java. lang.NullPointerException

java - Spring-Hibernate 应用程序中的 Whitelabel 错误页面

spring - Grails "remember me"不工作

multithreading - 在运行线程中 Autowiring 或注入(inject) Bean

java - 为什么我们在 spring OAuth 2.0 中将客户端密码作为纯文本存储在数据库中?