【问题标题】:Disable security for unit tests with spring boot使用 Spring Boot 禁用单元测试的安全性
【发布时间】:2015-09-19 02:33:00
【问题描述】:

我正在尝试创建一个具有安全性的简单 Spring Boot Web 项目。我可以很好地启动应用程序并且安全工作正常。但是,我有一些组件想要在没有安全性的情况下进行测试(或者根本无法测试——我根本无法进行测试)。

我收到一个异常,表明它找不到 ObjectPostProcessor,因此无法启动容器。

原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有找到符合条件的 bean [org.springframework.security.config.annotation.ObjectPostProcessor] 类型的依赖项

14:01:50.937 [main] 错误 os.boot.SpringApplication - 应用程序启动失败 org.springframework.beans.factory.BeanCreationException:创建名为“fmpdfApplication.ApplicationSecurity”的bean时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配方法:public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setObjectPostProcessor(org.springframework.security.config.annotation.ObjectPostProcessor) ;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为 [org.springframework.security.config.annotation.ObjectPostProcessor] 的合格 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注释:{} 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) ~[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) ~[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) ~[spring-boot-1.2.4.RELEASE.jar:1.2.4.RELEASE] 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:320) ~[spring-boot-1.2.4.RELEASE.jar:1.2.4.RELEASE] 在 org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:103) [spring-boot-1.2.4.RELEASE.jar:1.2.4.RELEASE] 在 org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:200) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12] 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:261) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:219) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12] 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12] 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12] 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12] 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12] 在 org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12] 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12] 在 com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) [junit-rt.jar:na] 在 com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) [junit-rt.jar:na] 在 com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) [junit-rt.jar:na] 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45] 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45] 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45] 在 java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45] 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) [idea_rt.jar:na] 原因:org.springframework.beans.factory.BeanCreationException:无法自动装配方法:public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setObjectPostProcessor(org.springframework.security.config.annotation.ObjectPostProcessor) ;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为 [org.springframework.security.config.annotation.ObjectPostProcessor] 的合格 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注释:{} 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:649) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] ...省略了43个常用框架 原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖找到[org.springframework.security.config.annotation.ObjectPostProcessor]类型的合格bean:预计至少有1个bean有资格作为此依赖的自动装配候选者。依赖注释:{} 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:606) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] ...省略了45个常用框架

我什至没有尝试测试与网络或安全相关的任何内容。我只是对我的一个组件进行单元测试。 我的单元测试(在 groovy 中)是这样的:

@RunWith(SpringJUnit4ClassRunner)
@SpringApplicationConfiguration(classes = FmpdfApplication)
@ActiveProfiles(["test", "mockstore"])
class PdfUpdaterTest {

    @Resource PdfUpdater pdfUpdater
    ...

而我的(相关)gradle 依赖项是:

compile("org.springframework.boot:spring-boot-starter-actuator")
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-jdbc")
testCompile("org.springframework.boot:spring-boot-starter-test")

我试过设置 management.security.enabled=false security.basic.enabled=false 但这并没有帮助

另一个相关信息:我需要自定义安全性,因此我遵循以下模式:

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
    ..

这是问题的一部分吗?如果相关,有没有办法制作这个@Lazy?

更新:如果我将单元测试标记为@WebIntegrationTest,那么一切正常——但它会启动一个嵌入式 tomcat 服务器。如何禁用 Spring Security 以对非 Web 事物进行单元测试?

【问题讨论】:

  • FmpdfApplication 是模拟/测试还是真正的应用程序类?
  • 如果您需要禁用安全性,那么它不是单元测试。这是一个集成测试。
  • 我相信对单元测试与集成测试定义的迂腐没什么价值。我倾向于更多地关注风险缓解、成本、耦合、发展以适应未来变化的能力之间的正确平衡——而不是教条但是自从这个小评论线程被带到门前:我认为 Justas 已经翻转了。安全基础设施是一个多组件的东西(您的身份验证系统,您的授权系统);集成测试是涵盖多个组件的事物,而单元测试专注于单个事物(并且通常模拟其他依赖组件)。

标签: spring-boot spring-test


【解决方案1】:

更新答案: 我最近了解到的另一个选项,如果我使用 MockMvc 和 AutoConfigureMockMvc 来测试我的控制器,我可以在其上设置 secure=false 以禁用适用于您的控制器的任何安全性。

@AutoConfigureMockMvc(secure = false)

如果不使用下面的基本身份验证。


您得到的异常与我得到的非常不同,但是如果您想在运行测试用例时禁用安全性,您可以尝试使用配置文件并使用测试配置文件的属性禁用基本安全性。这就是我所做的 -

  1. 在我的WebSecurityConfigurerAdapter 实现中添加了注释@Profile(value = {"development", "production"}) -
    @Configuration
    @EnableWebSecurity
    @Profile(value = {"development", "production"})
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

2。现在,在test/resources 中,创建application-test.yml 来定义测试配置文件的属性并添加这个 -

    # Security enable/disable
    security:
      basic:
        enabled: false

3。现在,在您的测试用例中,添加此注释以应用活动配置文件@ActiveProfiles(value = "test")。这就是我的班级的样子 -

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    @ActiveProfiles(value = "test")
    @IntegrationTest({"server.port=0"})
    public class SampleControllerIntegrationTest {

这样做禁用了我的测试用例的安全性,我能够访问经过身份验证的 URL。我希望这也适用于你。祝你好运!!!

【讨论】:

  • 接受的答案对我不起作用,我正在使用 OAuth2 并在资源服务器上执行此操作,因此通过 ResourceServerConfigurerAdapter 添加了 @Profile 注释,但其余部分相同,并且运行良好。
  • @AutoConfigureMockMvc(secure = false) 现已弃用。
  • 没有属性 - secure
  • @andrew17 你可以选择addFilters = false
【解决方案2】:

FmpdfApplication 可能使用@EnableAutoConfiguration 进行注释(或使用@SpringBootApplication 进行注释,后者使用@EnableAutoConfiguration 进行元注释),这将导致Spring Security 被通过自动配置拾取和配置。

如果您想查看正在自动配置的内容,请启动您的 Web 应用并访问 autoconfig 端点(例如,http://localhost:8080/autoconfig)。然后搜索“Security”以查看正在检测哪些“AutoConfiguration”类。

然后您可以通过排除这些类来禁用自动配置安全性,如下所示:

@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class, ManagementSecurityAutoConfiguration.class })

当然,您不希望将它们排除在生产部署之外。因此,您需要有一个单独的 @Configuration 类用于生产和测试。

问候,

山姆

附言您可能还会发现我对以下问题的回答也很有用:Spring-Boot module based integration testing

【讨论】:

  • 请注意 @EnableAutoConfiguration(exclude = {SecurityAutoconfiguration.class, ManagementWebSecurityAutoConfiguration.class}) 将在 src/test/java 中的 @SpringBootApplication 注释类上。另外注意使用ManagementWebSecurityAutoConfiguration.class(我用的是spring boot 1.3.0)
  • 仅供参考,我认为 /autoconfig 仅在您将执行器拉入 pom 时才有效。由于我没有,所以我把logging.level.org.springframework=DEBUG 放在src/test/resources/application.properties 中查看自动配置带来了什么的报告。
  • 不好的解释,对我没有帮助
【解决方案3】:

就我而言,@AutoConfigureMockMvc(addFilters = false) 帮助了我。

例子:

@WebMvcTest(MyController.class)
@AutoConfigureMockMvc(addFilters = false)
@TestPropertySource(locations="classpath:application-test.properties")
public class MyControllerTests {

干杯

【讨论】:

  • 正是我想要的!已从使用 Mockito 在每次测试之前手动设置 MockMvc 对象更改为使用这些注释以加载更多配置 bean,这些配置 bean 为可能影响控制器行为的生产应用程序设置 web mvc(例如 jackson ObjectMapper 配置)无需额外手动设置。
  • 用这个方法我加载 ApplicationContext 失败
  • 它对我有用!
【解决方案4】:

试试这个禁用spring boot security进行测试


@AutoConfigureMockMvc(secure = false)

@RunWith(SpringRunner.class)
@WebMvcTest(SampleController.class)
@AutoConfigureMockMvc(secure = false)
public class SampleControllerIntegrationTest {

【讨论】:

  • 我还需要@ActiveProfiles("test") 才能工作。
  • 现在已弃用。
  • 根据您的用例,您可以改用@AutoConfigureMockMvc(addFilters = false)
【解决方案5】:

尝试使用 Spring Security @WithMockUser 在测试中快速模拟用户。

http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#test

【讨论】:

    【解决方案6】:

    对我来说,我更新了我的测试注释来修复它。现在可以正常使用了。

    发件人:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    

    收件人:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @WebAppConfiguration
    @ActiveProfiles(value = "test")
    @AutoConfigureMockMvc(addFilters = false)
    

    【讨论】:

      【解决方案7】:

      如果您的应用程序不是基于 Web 的,但您需要 spring-security jar 作为依赖项,并且您不希望 spring-boot 在测试时为 spring-security 自动配置, 你可以添加

      @SpringBootTest(webEnvironment = WebEnvironment.NONE)
      

      在你的测试课中。

      【讨论】:

        【解决方案8】:

        如果您想使用 application.yml 解决问题,您可以执行以下操作(解决方案与 Sam Brannen 接受的答案相同,但使用属性文件)。 如果还没有,请在测试文件夹中创建一个 application.yml。

           spring:
             profiles:
               active: integration-test
           autoconfigure:
             exclude:
              - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
              - org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
        

        然后您将集成测试设置为:

        @SpringBootTest(webEnvironment = RANDOM_PORT)
        @ActiveProfiles("integration-test")
        

        【讨论】:

          【解决方案9】:

          对我来说,解决方法是更新我的测试注释。我换了:

          @SpringApplicationConfiguration(classes = { MyApplication.class })
          @RunWith(SpringJUnit4ClassRunner.class)
          

          @RunWith(SpringRunner.class)
          @SpringBootTest
          @ContextConfiguration(classes = MyApplication.class)
          

          【讨论】:

            【解决方案10】:

            另一种方法是使用@ActiveProfile。创建一个单独的 yml 文件,如 application-nosecurity.yml,内容如下:

            security:
              ignored: /**
            

            现在,用 @ActiveProfile("nosecurity") 注释 Test 类,您不想在其中使用如下安全性:

            @RunWith(SpringRunner.class)
            @SpringBootTest(classes = Application.class)
            @ActiveProfile("nosecurity")
            public class BlaBlaTest {
            
               ## Your Test Code 
            
            }
            

            【讨论】:

            • 这不再有效;你不能再从 yaml 文件自定义安全自动配置了。
            【解决方案11】:

            您可以将此注释添加到您的测试类中: @AutoConfigureMockMvc(addFilters = false)

            【讨论】:

              【解决方案12】:

              如果您只是在 webMvcTest 上遇到此错误,则必须排除这些测试的安全类配置:

              @EnableWebSecurity
              @EnableGlobalMethodSecurity(prePostEnabled = true)
              @Profile(value = {"!test"})
              public class XXXX extends WebSecurityConfigurerAdapter {
              

              【讨论】:

                猜你喜欢
                • 2019-03-30
                • 2016-01-02
                • 2017-12-27
                • 1970-01-01
                • 2014-07-16
                • 2020-06-11
                • 2016-10-15
                • 2016-05-03
                相关资源
                最近更新 更多