因此,按照本教程http://krams915.blogspot.com/2011/01/spring-security-3-full-acl-tutorial,我有一个使用 spring-security-acl(版本 3.2.7.RELEASE)的带有 JavaConfig 的 SpringBoot 应用程序.html除了我也在使用 OAuth。问题是 AclPermissionEvaluator 在运行时总是被 DenyAllPermissionEvaluator 替换。
TLDR;如何让 spring-security-acl 与 OAuth2Authentication 一起使用?每个都需要 @EnableGlobalMethodSecurity 但在不同的位置(GlobalMethodSecurityConfiguration 子类上的 acl 和应用程序上的 OAuth2)。但是,您不能将其定义两次。与此类似,但使用 OAuth2:如何在没有 XML 文件的情况下配置 Spring ACL)
pom.xml
<project>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<!-- <version>Brixton.M4</version> -->
<version>Angel.SR3</version>
</parent>
<dependencies>
<!-- Spring-boot and cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<!-- <version>4.1.0.BUILD-SNAPSHOT</version> -->
<!-- this is intentional to support non-numeric ID's e.g. UUIDs-->
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
<version>${postgres.version}</version>
</dependency>
</dependencies>
</project>
SpringBoot 应用程序
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.mycompany.mypackage.clients")
@EnableOAuth2Resource
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Java 配置
@Configuration
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class AclSecurityConfig extends GlobalMethodSecurityConfiguration {
@Value("${spring.datasource.url}")
private String jdbcUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
private String driverClass;
@Autowired
private ConversionService defaultConversionService;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
log.info("CreateExpressionHandler() got called");
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
try {
expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
} catch (PropertyVetoException e) {
throw new RuntimeException("Error creating expressionHandler", e);
}
return expressionHandler;
}
@Bean
public MutableAclService aclService() throws PropertyVetoException{
final JdbcMutableAclService mutableAclService = new JdbcMutableAclService(dataSource(), lookupStrategy(), aclCache());
mutableAclService.setClassIdentityQuery("select currval(pg_get_serial_sequence('acl_class', 'id'))");
mutableAclService.setSidIdentityQuery("select currval(pg_get_serial_sequence('acl_sid', 'id'))");
return mutableAclService;
}
public DataSource dataSource() throws PropertyVetoException {
final ComboPooledDataSource cpds = new ComboPooledDataSource(true);
cpds.setJdbcUrl(jdbcUrl);
cpds.setUser(username);
cpds.setPassword(password);
cpds.setDriverClass(driverClass);
return cpds;
}
@Bean
public BasicLookupStrategy lookupStrategy() throws PropertyVetoException {
return new BasicLookupStrategy(dataSource(), aclCache(), aclAuthorizationStrategy(), grantingStrategy(), this.defaultConversionService);
}
@Bean
public AclCache aclCache() {
return new EhCacheBasedAclCache(ehCacheManagerFactoryBean().getObject().getCache("aclCache"), grantingStrategy(), aclAuthorizationStrategy());
}
@Bean
public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean();
cacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
cacheManagerFactoryBean.setShared(true);
return cacheManagerFactoryBean;
}
@Bean
public AclAuthorizationStrategy aclAuthorizationStrategy() {
return new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_ADMIN"),
new SimpleGrantedAuthority("ROLE_ADMIN"),
new SimpleGrantedAuthority("ROLE_ADMIN"));
}
@Bean
public PermissionGrantingStrategy grantingStrategy(){
return new DefaultPermissionGrantingStrategy(auditLogger());
}
@Bean
public AuditLogger auditLogger(){
return new ConsoleAuditLogger();
}
}
控制器
@RepositoryRestController
@ResponseBody
public class SampleRepositoryController {
@Autowired
private MyRepository myRepository;
@PreAuthorize("hasRole('ROLE_USER') and hasPermission(#id, 'com.mycompany.mypackage.services.MyPojo', 'read')")
@RequestMapping(value = "/path/{id}/resource", method = RequestMethod.GET)
public MyObject file(@PathVariable("id") UUID id) {
return myRepository.findOne(id);
}
当我在运行时调试/逐步执行DefaultMethodSecurityExpressionHandler时,我可以说权限评估器始终是DenyAllPermissionEvaluator(而不是AclPermissionEvaluator),因为创建了新的 MethodSecurityEvaluationContext 。
请注意,我没有也不需要@EnableWebSecurity。
另外,我强烈怀疑这是因为我有
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true
)。
定义了两次,但是当我将其从 Application.java 中取出并运行应用程序(mvn spring-boot:run)时,它无法启动并出现以下错误:
2016-02-22 16:04:48.747 INFO 26533 --- [lication.main()] o.apache.catalina.core.StandardService : Stopping service Tomcat
2016-02-22 16:04:48.763 WARN 26533 --- [lication.main()] o.s.boot.SpringApplication : Error handling failed (Error creating bean with name 'delegatingApplicationListener' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'aclSecurityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration.setApplicationContext(org.springframework.context.ApplicationContext); nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.config.internalCacheAdvisor' defined in class path resource [org/springframework/cache/annotation/ProxyCachingConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor]: Factory method 'cacheAdvisor' threw exception; nested exception is java.lang.NullPointerException)
2016-02-22 16:04:48.764 ERROR 26533 --- [lication.main()] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at com.advaita.cloud.services.samples.Application.main(Application.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.boot.maven.RunMojo$LaunchRunner.run(RunMojo.java:418)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 23 common frames omitted
Caused by: java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
at org.springframework.util.Assert.notNull(Assert.java:112)
有谁知道如何让两个人一起玩得好?