2016-01-15 52 views
3

我有一個Spring Boot應用程序,我想添加Spring Security。所以我添加了以下配置,該配置啓動並運行得很好:爲什麼我的ApplicationContext在啓用Web安全性時無法加載?

@Configuration 
@EnableWebSecurity 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Resource 
    private Environment environment; 

    @Bean 
    public PasswordEncoder passwordEncoder(){ 
     return new BCryptPasswordEncoder(); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     if(environment.acceptsProfiles("live")) { 
      http.requiresChannel().anyRequest().requiresSecure(); 
     } 
     http.csrf().disable(); 
    } 
} 

問題是我的功能測試無法加載應用程序上下文。

@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = MyConfiguration.class) 
@WebAppConfiguration 
@IntegrationTest 
class ContextInitializer extends GebReportingSpec { 
} 

當測試試圖加載該應用程序,它引發以下堆棧跟蹤:所有功能測試從以下配置延伸

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:1123) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) 
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:117) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:689) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321) 
    at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:103) 
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) 
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) 
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228) 
    at org.spockframework.spring.SpringTestContextManager.prepareTestInstance(SpringTestContextManager.java:49) 
    at org.spockframework.spring.SpringInterceptor.interceptSetupMethod(SpringInterceptor.java:42) 
    at org.spockframework.runtime.extension.AbstractMethodInterceptor.intercept(AbstractMethodInterceptor.java:28) 
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87) 
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:471) 
    at org.spockframework.runtime.BaseSpecRunner.runSetup(BaseSpecRunner.java:375) 
    at org.spockframework.runtime.BaseSpecRunner.runSetup(BaseSpecRunner.java:370) 
    at org.spockframework.runtime.BaseSpecRunner.doRunIteration(BaseSpecRunner.java:323) 
    at org.spockframework.runtime.BaseSpecRunner$6.invoke(BaseSpecRunner.java:309) 
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:88) 
    at org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor$1.evaluate(AbstractRuleInterceptor.java:37) 
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55) 
    at org.spockframework.runtime.extension.builtin.TestRuleInterceptor.intercept(TestRuleInterceptor.java:38) 
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87) 
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:471) 
    at org.spockframework.runtime.BaseSpecRunner.runIteration(BaseSpecRunner.java:288) 
    at org.spockframework.runtime.BaseSpecRunner.initializeAndRunIteration(BaseSpecRunner.java:278) 
    at org.spockframework.runtime.BaseSpecRunner.runSimpleFeature(BaseSpecRunner.java:269) 
    at org.spockframework.runtime.BaseSpecRunner.doRunFeature(BaseSpecRunner.java:263) 
    at org.spockframework.runtime.BaseSpecRunner$5.invoke(BaseSpecRunner.java:246) 
    at org.spockframework.runtime.BaseSpecRunner.invokeRaw(BaseSpecRunner.java:480) 
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:463) 
    at org.spockframework.runtime.BaseSpecRunner.runFeature(BaseSpecRunner.java:238) 
    at org.spockframework.runtime.BaseSpecRunner.runFeatures(BaseSpecRunner.java:188) 
    at org.spockframework.runtime.BaseSpecRunner.doRunSpec(BaseSpecRunner.java:98) 
    at org.spockframework.runtime.BaseSpecRunner$1.invoke(BaseSpecRunner.java:84) 
    at org.spockframework.runtime.BaseSpecRunner.invokeRaw(BaseSpecRunner.java:480) 
    at org.spockframework.runtime.BaseSpecRunner.invoke(BaseSpecRunner.java:463) 
    at org.spockframework.runtime.BaseSpecRunner.runSpec(BaseSpecRunner.java:76) 
    at org.spockframework.runtime.BaseSpecRunner.run(BaseSpecRunner.java:67) 
    at org.spockframework.runtime.Sputnik.run(Sputnik.java:63) 
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:105) 
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:56) 
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:64) 
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50) 
    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.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) 
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) 
    at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) 
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) 
    at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) 
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:106) 
    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.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) 
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) 
    at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360) 
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) 
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    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) 
    ... 78 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:115) 
    at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.<init>(DefaultServletHandlerConfigurer.java:53) 
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:426) 
    at org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$4bbac173.CGLIB$defaultServletHandlerMapping$25(<generated>) 
    at org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$4bbac173$$FastClassBySpringCGLIB$$59db630c.invoke(<generated>) 
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) 
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318) 
    at org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$4bbac173.defaultServletHandlerMapping(<generated>) 
    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.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) 
    ... 79 common frames omitted 

好像我需要讓集成測試上下文加載不知何故知道春天的安全。

編輯:

我已經縮小問題到,在一個拉動的PasswordEncoder一個轉換器。卸下轉換器並直接在控制器中使用PasswordEncoder會導致問題消失。此外,刪除安全配置將允許我使用轉換器就好了。

這裏是我做了複製這一問題的倉庫的鏈接: https://github.com/StephenTurley/SpringBootSecurityTest.git

最後一次提交會導致錯誤。不知道爲什麼我不能使用彈簧轉換器和Spring安全。有任何想法嗎?

+0

過去,Spock的Spring支持存在問題。你用簡單的JUnit試過了嗎?另外,你使用的是什麼版本的Spock?一個[最小的,完整的和可驗證的例子](http://stackoverflow.com/help/mcve)在這裏將是一個很大的幫助。 –

+0

還沒有試過junit,因爲我們所有的功能測試都是用Spock/Jeb編寫的,重寫它們並不理想。話雖如此,我今天將彙集一個小項目來重現這個問題。並張貼它。謝謝參觀。 – ZeroDivide

+0

我還應該補充說,當安全配置不存在時,我們的測試工作正常。 – ZeroDivide

回答

1

我懷疑這是一個初始化問題,在引導1.3中支持fixed by adding DelegatingFilterProxy。我向您發送了一個pull request,通過更新到Spring Boot 1.3.2.RELEASE來解決此問題。它還解決了我遇到的其他一些依賴性問題。

0

遇到了同樣的問題,有時背部和固定它測試範圍加入javax.servlet-apijsp-api,你可以嘗試添加相同的依賴關係,下面以供參考:

對Maven:

<dependency> 
    <groupId>javax.servlet</groupId> 
    <artifactId>javax.servlet-api</artifactId> 
    <version>3.0.1</version> 
</dependency> 
<dependency> 
    <groupId>javax.servlet</groupId> 
    <artifactId>jsp-api</artifactId> 
    <version>2.0</version> 
</dependency> 

For Gradle:

testCompile "javax.servlet:javax.servlet-api:3.0.1" 
testCompile "javax.servlet:jsp-api:2.0" 

此外請確保您的依賴測試範圍在您的類路徑中。

+0

添加這些依賴關係後沒有變化。 – ZeroDivide

+0

@ZeroDivide:你的'classpath'中是否有spring-context(http://mvnrepository.com/artifact/org.springframework/spring-context)依賴項? – Arpit

+1

我認爲這是從春季開機過渡拉動。我正在編寫一個小例子來重現這個問題。我不確定我的午餐時間結束時是否能完成。我會在完成時分享回購。 – ZeroDivide

0

我想在你的應用程序上下文建議立即進行刪除包括安全上下文,所以要儘量添加在你的應用程序上下文:

@Configuration 
@Import({ 
    SecurityConfiguration.class 
}) 
@ComponentScan(basePackages = { 
    }) 
public class ApplicationContext { 
} 

Anothing,我覺得應該SecurityConfiguration被稱爲SecurityContext中。

0

我可以在這裏缺少一些背景信息,但你嘗試過:

@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,WebMvcAutoConfiguration.class }) 

也許你@Configuration類的一個標註有@EnableWebMvc?

相關問題