Spring securityconfig 中断了 google 云应用引擎上的部署

Spring securityconfig breaks deployment on google cloud app engine

我正在尝试将 springboot rest api 部署到 google 云的应用引擎,但是我收到此错误:

org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.

这是由这个 class 引起的,它扩展了 websecurityConfigurerAdapter 确切地说:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    APIUserDetailsService apiUserDetailsService;

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(apiUserDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

    private static final String[] AUTH_WHITELIST = {"/hello"};

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors().and()
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(STATELESS).and()
                .authorizeRequests()
                .antMatchers(AUTH_WHITELIST).permitAll()
                .anyRequest().authenticated()
                .and()
                .httpBasic();

        http.headers().frameOptions().disable();
    }

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

}

删除此 class 完全修复了错误, 该应用程序部署在应用程序引擎上并完美运行,尽管以没有安全性为代价。到目前为止,据我所知,我们似乎必须使用 google 应用引擎的 Web 服务器,而不是 spring 中嵌入的默认 tomcat。因此,当应用程序部署时,它会尝试扩展不存在的 WebSecurityConfigurerAdapter,因为没有嵌入式 tomcat Web 服务器。我一直在努力寻找一种方法让它使用 googles 网络服务器,有谁知道在 google 应用引擎上使用它的方法吗?

POM xml:

<parent>
    <properties>
        <java.version>11</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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter-sql-mysql</artifactId>
            <version>1.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

    </dependencies>
</project>

主要内容:

@SpringBootApplication
@EnableCaching
public class OwlServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(OwlServerApplication.class, args);

    }

错误的完整堆栈跟踪:

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh (ServletWebServerApplicationContext.java:162)
at
org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:582)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh (ServletWebServerApplicationContext.java:144)
at
org.springframework.boot.SpringApplication.refresh (SpringApplication.java:767)
at
org.springframework.boot.SpringApplication.refresh (SpringApplication.java:759)
at
org.springframework.boot.SpringApplication.refreshContext (SpringApplication.java:426)
at
org.springframework.boot.SpringApplication.run (SpringApplication.java:326)
at
org.springframework.boot.SpringApplication.run (SpringApplication.java:1309)
at
org.springframework.boot.SpringApplication.run (SpringApplication.java:1298)
at
com.owl.owlserver.OwlServerApplication.main (OwlServerApplication.java:12)
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory (ServletWebServerApplicationContext.java:209)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer (ServletWebServerApplicationContext.java:179)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh (ServletWebServerApplicationContext.java:159)

通过添加。 3.1 servlet 我们现在得到这个错误:

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.example.demo.DemoApplication]; nested exception is java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.class] cannot be opened because it does not exist
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:339)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1340)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329)
    at com.example.demo.DemoApplication.main(DemoApplication.java:18)
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.class] cannot be opened because it does not exist
    at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:187)
    at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:55)
    at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:49)
    at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103)
    at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:86)
    at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:73)
    at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81)
    at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:696)
    at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getSuperClass(ConfigurationClassParser.java:1010)
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:341)
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199)
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:304)
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175)
    ... 14 common frames omitted 

应用引擎似乎找不到 websecurityconfigurerAdapter class。

虽然我不确定是什么导致了这个问题,但这里常见的解决方案是通过以下方式配置自动配置。

@EnableAutoConfiguration
@SpringBootApplication
@EnableCaching
public class OwlServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(OwlServerApplication.class, args);

    }

这个注解@EnableAutoConfiguration确保可以从兄弟或子包路径扫描配置bean,也可以自动配置。

同时,请确保您在同一个或同级包中有 ApplicationSecurityConfig class。


Springboot 和 Google App Engine 都没有明确提到这个 Servlet 版本问题。

我在这里 找到了这个答案。

如果我猜对了(我之前从未使用过 Google App Engine),Google App Engine 支持 Sevlet 2.5 但它需要上面的 Servlet 3.1 才能正确初始化扩展的 bean WebSecurityConfigurerAdapter.

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.1.0</version>
  <type>jar</type>
  <scope>provided</scope>
</dependency>

另请参阅 Google Cloud Engine 的官方指南以迁移到 Servlet 3.1 https://javaee.github.io/servlet-spec/ 另见答案


让我知道它是否有效或还有更多问题需要讨论。