使用“spring-boot-starter-oauth2-resource-server”设置资源服务器时,不会自动注入 JwtDecoder bean

Posted

技术标签:

【中文标题】使用“spring-boot-starter-oauth2-resource-server”设置资源服务器时,不会自动注入 JwtDecoder bean【英文标题】:JwtDecoder bean is not injected automatically while setting a ressource server using 'spring-boot-starter-oauth2-resource-server' 【发布时间】:2021-10-26 10:02:57 【问题描述】:

我正在使用“spring-boot-starter-oauth2-resource-server”设置资源服务器:

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-oauth2-resource-server'

我已经设置了一个简单的安全配置,如下所示:

@Configuration
@EnableWebSecurity
class EndpointsSecurityConfig : WebSecurityConfigurerAdapter() 

    override fun configure(web: WebSecurity) 
        web.ignoring().antMatchers("/live")
    

    override fun configure(http: HttpSecurity?) 
        http?.cors()
        http?.sessionManagement()?.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        http?.csrf()?.disable()
        http
            ?.authorizeRequests()
            ?.anyRequest()
            ?.authenticated()
            ?.and()
            ?.oauth2ResourceServer()
            ?.jwt()
    

在我的 application.yml 中,我像这样添加了 issuer-uri:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://cognito-idp.$AWS_REGION:eu-central-1.amazonaws.com/$COGNITO_USER_POOL_ID:testUserPoolId

正如我在许多教程和官方文档中看到的那样,此配置非常简约,无需任何额外配置即可开箱即用,但我的应用程序无法启动并出现以下错误:

Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' available
   at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:656)

所以这里的问题是 JwtDecoder bean 找不到,即使它在 OAuth2ResourceServerJwtConfiguration 类中声明并且受我在 application.yml 中设置的 issuer-uri 的限制。

作为一种解决方法,我自己重新声明了 bean:

@Configuration
@EnableWebSecurity
class EndpointSecurityConfig(@Value("\$spring.security.oauth2.resourceserver.jwt.issuer-uri") private val issuerUri: String) : WebSecurityConfigurerAdapter() 

    override fun configure(web: WebSecurity) 
        web.ignoring().antMatchers("/live")
    

    override fun configure(http: HttpSecurity?) 
        http?.cors()
        http?.sessionManagement()?.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        http?.csrf()?.disable()
        http
            ?.authorizeRequests()
            ?.anyRequest()
            ?.authenticated()
            ?.and()
            ?.oauth2ResourceServer()
            ?.jwt()
    

    @Bean
    @Conditional(IssuerUriCondition::class)
    fun jwtDecoderByIssuerUri(): JwtDecoder? 
        return JwtDecoders.fromIssuerLocation(issuerUri)
    

这是可行的,但我不明白为什么开箱即用的配置不适合我?

更新:gradle 配置


plugins 
    id 'java'
    id "io.spring.dependency-management" version "1.0.9.RELEASE"
    id "org.springframework.boot" version "2.2.5.RELEASE"
    id "org.owasp.dependencycheck" version "6.0.2"


// irrelevent details

dependencies 
    ktlint "com.pinterest:ktlint:0.34.2"

    implementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: '1.3.70'
    implementation group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: '1.3.70'
    implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.0'

    implementation group: 'org.springframework.boot', name: 'spring-boot-starter', version: '2.3.4.RELEASE'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.3.4.RELEASE'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-log4j2', version: '2.3.4.RELEASE'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.3.4.RELEASE'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jdbc', version: '2.3.4.RELEASE'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '2.3.4.RELEASE'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-oauth2-resource-server', version: '2.3.4.RELEASE'

    implementation group: 'com.amazonaws', name: 'aws-java-sdk-secretsmanager', version: "1.11.875"

    implementation group: 'com.oracle.database.jdbc', name: 'ojdbc8', version: "19.7.0.0"

    implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.10.2'

    implementation group: 'org.springdoc', name: 'springdoc-openapi-kotlin', version: '1.4.3'
    implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.4.3'

    runtime group: 'com.h2database', name: 'h2', version: '1.4.194'

    testImplementation group: 'io.mockk', name: 'mockk', version: '1.9.3'
    testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.3.4.RELEASE'
    testImplementation group:'org.springframework.security', name: 'spring-security-test'


【问题讨论】:

你很可能不需要导入,oauth 已经包含在 spring security 中。尝试删除导入。 你使用的是什么版本的 Spring Boot? @SteveRiesenberg 我正在使用 Spring Boot 的“2.3.4.RELEASE”版本 @Toerktumlare oauth2-resource-server 不包含在 spring security 中,至少从与 spring boot 2.3.4.RELEASE 捆绑在一起的 5.2.2 版本开始 @youneselmorabit,升级到2.3.12.RELEASE 后有什么变化吗?日志中还有其他错误吗? issuer-uri 似乎无效或无法解析(例如 UnknownHostException、SocketTimeoutException 等)。 【参考方案1】:

我发现我正在处理的项目的 gradle 配置存在问题(更新了问题)。 Spring Boot 依赖项是使用版本“2.3.4.RELEASE”声明的,而 org.springframework.boot 插件版本是“2.2.5.RELEASE”,我认为这一定导致了 spring 依赖项之间的某种不兼容。

作为解决方案,我从 spring 依赖项中删除了版本声明,并将插件版本设置为“2.3.4.RELEASE”,现在错误消失了,oauth2 资源服务器配置无需任何额外配置即可工作。

注意:

我注意到,当我将插件版本保持在“2.2.5.RELEASE”时,错误仍然存​​在,除非我删除插件io.spring.dependency-management,否则开箱即用的配置不起作用。

【讨论】:

以上是关于使用“spring-boot-starter-oauth2-resource-server”设置资源服务器时,不会自动注入 JwtDecoder bean的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)