【发布时间】:2016-02-23 07:14:07
【问题描述】:
我正在将 Spring MVC servlet 3.1 应用程序移至 Spring Boot 1.3.0,当我将 @EnableGlobalMethodSecurity 注释添加到我的 Java 配置类之一时,我在启动时遇到异常(完整如下)。
我将 WebSecurityConfigurerAdapter 子类化为我的 Spring 安全支持(以前对我来说效果很好)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityAuthorisationConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf()...
即使在类中没有其他依赖项@Autowired,启动也会失败。如果我删除 @EnableGlobalMethodSecurity 注释,启动将成功,但显然没有方法安全性。大多数其他网络安全 SO 帖子似乎是由于安全配置无法在调度程序 servlet 之前启动,但我的安全配置中没有其他依赖项,我不明白为什么会发生这种情况。
我尝试了很多方法来启动应用程序并更改了安全配置的@Order,但无济于事。
我当前的应用程序入口点看起来像这样,虽然我也尝试过使用自动魔法调度程序进行初始化,但我遇到了同样的问题:
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = { "com.myapp.config.web", "com.myapp.config.app" })
public class Application extends SpringBootServletInitializer {
private static Class<Application> applicationClass = Application.class;
public static void main(final String[] args) throws Exception {
SpringApplication.run(applicationClass, args);
}
@Autowired
private AuditLogger auditLogger;
@Override
public void onStartup(final ServletContext container) throws ServletException {
final AnnotationConfigWebApplicationContext rootContext = createRootContext(container);
setUpSessionConfig(container);
setUpMdcLoggingFilter(container);
setAllUndefinedRequestsToUtf8(container);
setUpAuditLogging(container);
addSecurityFilter(container);
addUpdateExpiredPasswordFilter(container);
createDispatcher(container, rootContext);
}
private void setUpSessionConfig(final ServletContext container) {
container.getSessionCookieConfig().setHttpOnly(true);
container.setSessionTrackingModes(asSet(SessionTrackingMode.COOKIE));
}
private void setUpMdcLoggingFilter(final ServletContext container) {
final Dynamic mdcFilter = container.addFilter("mdcInsertingFilter",
new DelegatingFilterProxy(mdcInsertingFilter()));
mdcFilter.addMappingForUrlPatterns(null, true, "/*");
}
private void addUpdateExpiredPasswordFilter(final ServletContext container) {
final Dynamic filter = container.addFilter("updateExpiredPasswordFilter",
new DelegatingFilterProxy(updateExpiredPasswordFilter()));
filter.addMappingForUrlPatterns(null, true, "/*");
}
private void setUpAuditLogging(final ServletContext container) {
final Dynamic auditLoggingFilter = container.addFilter("auditLogFilter",
new DelegatingFilterProxy(auditLogFilter()));
auditLoggingFilter.addMappingForUrlPatterns(null, true, "/*");
}
private void addSecurityFilter(final ServletContext container) {
final Dynamic securityFilter =
container.addFilter(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME,
DelegatingFilterProxy.class);
securityFilter.addMappingForUrlPatterns(null, true, "/*");
}
private AnnotationConfigWebApplicationContext createRootContext(final ServletContext servletContext) {
final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
rootContext.setServletContext(servletContext);
servletContext.addListener(new ContextLoaderListener(rootContext));
servletContext.setInitParameter("spring.profiles.default", "production");
return rootContext;
}
private void setAllUndefinedRequestsToUtf8(final ServletContext container) {
final FilterRegistration filter = container.addFilter("encodingFilter", OrderedCharacterEncodingFilter.class);
filter.setInitParameter("encoding", "UTF-8");
filter.addMappingForUrlPatterns(null, true, "/*");
}
private void createDispatcher(final ServletContext container,
final AnnotationConfigWebApplicationContext rootContext) {
final DispatcherServlet dispatcherServlet = new DispatcherServlet(rootContext);
final ServletRegistration.Dynamic dispatcher =
container.addServlet("myServlet", dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
@Bean
public AuditLogFilter auditLogFilter() {
final AuditLogFilter auditLogFilter = new AuditLogFilter();
auditLogFilter.setAuditLogger(auditLogger);
auditLogFilter.setIgnoredPaths("/resources,/webjars");
return auditLogFilter;
}
@Bean
public UpdateExpiredPasswordFilter updateExpiredPasswordFilter() {
final UpdateExpiredPasswordFilter filter = new UpdateExpiredPasswordFilter();
filter.setPasswordUpdateFormPath("/user/change_password");
filter.setPasswordUpdatePath("user/change_password");
filter.setLogoutPath("/logout");
filter.setIgnoredPaths("/resources,/webjars");
return filter;
}
@Bean(name = "mdcInsertingFilter")
public MDCInsertingServletFilter mdcInsertingFilter() {
return new MDCInsertingServletFilter();
}
}
虽然我不一定期望得到一个全面的解决方案,但知道从哪里开始寻找问题的原因会非常有用。它是一个错误吗?可能与我创建应用程序的方式有关吗?
堆栈跟踪:
2015-11-20 17:18:02.337 错误 80806 --- [main] os.boot.SpringApplication:应用程序启动失败 org.springframework.beans.factory.BeanCreationException:在类路径资源 [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class] 中定义名称为“defaultServletHandlerMapping”的 bean 创建错误:通过工厂方法进行 Bean 实例化失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframework.web.servlet.HandlerMapping]:工厂方法“defaultServletHandlerMapping”抛出异常;嵌套异常是 java.lang.IllegalArgumentException:需要 ServletContext 来配置默认 servlet 处理 在 org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:838) ~[spring-context-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) ~[spring-context-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE] 在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE] 在 org.springframework.boot.SpringApplication.doRun(SpringApplication.java:347) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE] 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:295) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE] 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:1112) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE] 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:1101) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE] 在 com.amberhill.web.Application.main(Application.java:51) [bin/:na] 原因:org.springframework.beans.BeanInstantiationException:无法实例化[org.springframework.web.servlet.HandlerMapping]:工厂方法'defaultServletHandlerMapping'抛出异常;嵌套异常是 java.lang.IllegalArgumentException:需要 ServletContext 来配置默认 servlet 处理 在 org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] ...省略了18个常用框架 原因:java.lang.IllegalArgumentException:需要 ServletContext 来配置默认 servlet 处理 在 org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.(DefaultServletHandlerConfigurer.java:53) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:450) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$5204f0e6.CGLIB$defaultServletHandlerMapping$34() ~[spring-boot-autoconfigure-1.3.0.RELEASE.jar:1.3.0.RELEASE] 在 org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$5204f0e6$$FastClassBySpringCGLIB$$7ec661f1.invoke() ~[spring-boot-autoconfigure-1.3.0.RELEASE.jar:1.3.0.发布] 在 org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318) ~[spring-context-4.2.3.RELEASE.jar:4.2.3.RELEASE] 在 org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$5204f0e6.defaultServletHandlerMapping() ~[spring-boot-autoconfigure-1.3.0.RELEASE.jar:1.3.0.RELEASE] 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_11] 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_11] 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_11] 在 java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_11] 在 org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE] ...省略了19个常用框架
【问题讨论】:
标签: spring-security spring-boot