各位专家,
我目前正在学习 Spring Boot,我想将它与 Spring Security ACL 一起使用。按照Spring Security的文档和Baeldung.com上的教程,我想我对需要什么有所了解。我还研究了Spring 的 DMS 示例。我通过寻找解决方案偶然发现了另一个例子。
基于这些信息,我构建了我的应用程序。作为参考,您可以在GitHub 上找到当前应用程序。
当前问题
当我启动应用程序时,我被java.lang.IllegalStateException: No ServletContext set
抛出了。据我了解,这是因为在 Spring Boot 的自动配置魔术期间,我的@Configuration
注释类在初始化之前ServletContext
被初始化。
链接到pastebin上的完整堆栈跟踪。
到目前为止我做了什么
根据我的研究(主要是在 StackOverflow 上)和我目前对该问题的理解,将负责Bean
的 s 放入自己的带@Configuration
注释的类中应该会有所帮助。不幸的是,我现在迷路了。相关问题使我产生了这种想法(请参阅此问题或此问题。)
我的环境
- macOS 10.12.6
- jdk1.8.0_144
- IntelliJ IDEA 2017.3.3(终极版)
- Spring Boot v1.5.9.RELEASE
相关项目文件
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.moritzrupp</groupId>
<artifactId>traderdiary</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Trader Diary</name>
<description>Trader Diary is an easy to use web application to create a journal
about your trades with great reporting on top of it.</description>
<licenses>
<license>
<name>GNU General Public License (GPL) v3.0</name>
<url>https://www.gnu.org/licenses/gpl-3.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<id>moritzrupp</id>
<name>Moritz Rupp</name>
<email>moritz.rupp@gmail.com</email>
<url>https://www.moritzrupp.de</url>
<timezone>DE</timezone>
</developer>
</developers>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.11</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
应用程序属性
# --------------------------------------------
# Datasource Properties
# --------------------------------------------
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.url=jdbc:h2:mem:trader-diary-h2-db
spring.datasource.platform=h2
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
TraderDiaryApplication.java
@SpringBootApplication
public class TraderDiaryApplication {
public static void main(String[] args) {
SpringApplication.run(TraderDiaryApplication.class, args);
}
}
数据源配置.java
@Configuration
public class DataSourceConfig {
@Bean
public DataSource traderDiaryDataSource(DataSourceProperties
dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().build();
}
}
WebSecurityConfig.java
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("traderDiaryDataSource")
private DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
// I think it is not relevant for the issue, see GitHub repo
...
}
@Bean
public PasswordEncoder passwordEncoder() {
// I think it is not relevant for the issue, see GitHub repo
...
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider(...) {
// I think it is not relevant for the issue, see GitHub repo
...
}
@Bean
public MethodSecurityExpressionHandler aclExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
AclPermissionCacheOptimizer permissionCacheOptimizer =
new AclPermissionCacheOptimizer(aclService());
expressionHandler.setPermissionEvaluator(permissionEvaluator());
expressionHandler
.setPermissionCacheOptimizer(permissionCacheOptimizer);
return expressionHandler;
}
@Bean
public PermissionEvaluator permissionEvaluator() {
return new AclPermissionEvaluator(aclService());
}
@Bean
public JdbcMutableAclService aclService() {
return new JdbcMutableAclService(dataSource, lookupStrategy(),
aclCache());
}
@Bean
public LookupStrategy lookupStrategy() {
return new BasicLookupStrategy(dataSource, aclCache(),
aclAuthorizationStrategy(), new ConsoleAuditLogger());
}
@Bean
public EhCacheBasedAclCache aclCache() {
return new EhCacheBasedAclCache(aclEhCacheFactoryBean().getObject(),
permissionGrantingStrategy(), aclAuthorizationStrategy());
}
@Bean
public EhCacheFactoryBean aclEhCacheFactoryBean() {
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
ehCacheFactoryBean.setCacheName("aclCache");
return ehCacheFactoryBean;
}
@Bean
public EhCacheManagerFactoryBean aclCacheManager() {
return new EhCacheManagerFactoryBean();
}
@Bean
public PermissionGrantingStrategy permissionGrantingStrategy() {
return new DefaultPermissionGrantingStrategy(new
ConsoleAuditLogger());
}
@Bean
public AclAuthorizationStrategy aclAuthorizationStrategy() {
return new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_ADMIN"));
}
/* This is due to an earlier issue: DataSource required */
@Configuration
protected static class AclMethodSecurityConfig extends
GlobalMethodSecurityConfiguration {
@Autowired
@Qualifier("daoAuthenticationProvider")
private AuthenticationProvider authenticationProvider;
@Autowired
@Qualifier("aclExpressionHandler")
private MethodSecurityExpressionHandler aclExpressionHandler;
@Autowired
public void configureAuthManager(AuthenticationManagerBuilder
authenticationManagerBuilder) {
authenticationManagerBuilder
.authenticationProvider(authenticationProvider);
}
@Override
protected MethodSecurityExpressionHandler
createExpressionHandler() {
return aclExpressionHandler;
}
}
}
非常感谢所有输入!如果需要任何进一步的信息,我会很乐意提供。
谢谢和最好的问候莫里茨