【问题标题】:Spring boot unresolved reference oauth2 resource serverSpring Boot 未解析的引用 oauth2 资源服务器
【发布时间】:2021-08-04 12:24:42
【问题描述】:

不久前我问了一个问题以了解how to validate jwt token using spring boot 并复制了示例here 的依赖关系,但将它们更新为最新的。

这是我的 build.gradle:

import org.apache.tools.ant.filters.ReplaceTokens

plugins {
    id 'org.springframework.boot' version '2.4.5'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'org.jetbrains.kotlin.jvm' version '1.4.32'
    id 'org.jetbrains.kotlin.plugin.spring' version '1.4.32'
    id "org.jetbrains.kotlin.plugin.jpa" version "1.4.32"
}

apply plugin: 'io.spring.dependency-management'
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'kotlin-jpa'

group = 'com.backend-project'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {

    def appInsightsVersion = '2.6.2'

    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-websocket'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
    implementation 'com.microsoft.sqlserver:mssql-jdbc:6.2.1.jre8'
    implementation 'com.h2database:h2:1.4.199'
    implementation 'io.springfox:springfox-swagger2:2.9.2'
    implementation 'io.springfox:springfox-swagger-ui:2.9.2'
    implementation 'org.jetbrains.kotlin:kotlin-reflect'
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
    implementation 'org.hibernate:hibernate-core'
    implementation 'javax.xml.bind:jaxb-api'
    implementation group: 'com.microsoft.azure', name: 'applicationinsights-web', version: appInsightsVersion
    implementation group: 'com.microsoft.azure', name: 'applicationinsights-logging-logback', version: appInsightsVersion
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    implementation 'org.springframework.boot:spring-boot-starter-validation:2.4.5'
    implementation 'org.springframework.boot:spring-boot-starter-security:2.4.5'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.4.5'
    implementation 'org.springframework.security:spring-security-oauth2-jose:5.3.9.RELEASE'
    compile 'org.springframework.security:spring-security-oauth2-core:5.3.9.RELEASE'

    compile 'io.jsonwebtoken:jjwt-api:0.11.2'
    runtime 'io.jsonwebtoken:jjwt-impl:0.11.2',
            'io.jsonwebtoken:jjwt-jackson:0.11.2'
    compile 'joda-time:joda-time:2.10.10'
    implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.68'


}

compileKotlin {
    kotlinOptions {
        freeCompilerArgs = ['-Xjsr305=strict']
        jvmTarget = '1.8'
    }
}

compileTestKotlin {
    kotlinOptions {
        freeCompilerArgs = ['-Xjsr305=strict']
        jvmTarget = '1.8'
    }
}


task copyWebConfig(type: Copy) {
    from("$rootDir/src/main/templates") {
        include 'web.config'
    }
    into "$buildDir/libs"
    filter(ReplaceTokens, tokens: [VERSION: project.version])
    inputs.property("VERSION", project.version)
    filter(ReplaceTokens, tokens: [PACKAGE_NAME: project.name])
    inputs.property("PACKAGE_NAME", project.name)

}

task copyLogBack(type: Copy) {
    from("$rootDir") {
        include 'logback-spring.xml'
    }
    into "$buildDir/libs"
}

assemble.dependsOn(copyWebConfig)
assemble.dependsOn(copyLogBack)

这是我的网络安全实现:

package com.renaulttrucks.transfertprotocolbackend.security.config

import com.renaulttrucks.transfertprotocolbackend.api.config.Router
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.oauth2.jwt.JwtDecoder
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder
import org.springframework.util.ResourceUtils
import java.io.FileInputStream
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.security.interfaces.RSAPublicKey

@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {

    @Value("\${security.enabled}")
    val securityEnabled : Boolean? = false

    @Value("\${jwt.key-path}")
    var keyPath: String? = null

    var publicKey: RSAPublicKey? = null

    override fun configure(http: HttpSecurity) {

        if(!securityEnabled!!) {
            http.httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers("/**").permitAll()
                .and()
                .csrf().disable()
                .formLogin().disable()
        } else {
            http
                .authorizeRequests()
                .antMatchers("/api/companies/**").permitAll()
                .antMatchers(Router.API_PATH + "/**").authenticated()
                .and()
                .httpBasic()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .anonymous()
                .and()
                .securityContext()
                .and()
                .headers().disable()
                .rememberMe().disable()
                .requestCache().disable()
                .csrf().disable()
                .x509().disable()
                .httpBasic().disable()
                .formLogin().disable()
                .logout().disable()
                .oauth2ResourceServer(oauth2 -> oauth2
                    .jwt(jwt -> jwt.decoder(jwtDecoder()))
                )
        }
    }

    @Bean
    fun jwtDecoder(): JwtDecoder? {
        return NimbusJwtDecoder.withPublicKey(getPublicKeyFromString()).build()
    }

    fun getPublicKeyFromString(): RSAPublicKey? {
        if (this.publicKey != null) {
            return this.publicKey
        }
        val fin = FileInputStream(ResourceUtils.getFile(keyPath!!))
        val f: CertificateFactory = CertificateFactory.getInstance("X.509")
        val certificate: X509Certificate = f.generateCertificate(fin) as X509Certificate
        publicKey = certificate.getPublicKey() as RSAPublicKey?
        return publicKey
    }

}

错误发生在这里:

它给了我以下错误,我不明白为什么我会得到,因为我正在关注文档:

即使在尝试像here 这样的 kotlin dsl 版本时,也可以像下面这样更改我的配置功能:

    override fun configure(http: HttpSecurity) {
        http {
            authorizeRequests {
                authorize(anyRequest, authenticated)
            }
            oauth2ResourceServer {
                jwt {
                    jwtDecoder = jwtDecoder()
                }
            }
        }
    }

它给了我以下错误: 第一行是这个:: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public operator fun <T, R> DeepRecursiveFunction<TypeVariable(T), TypeVariable(R)>.invoke(value: TypeVariable(T)): TypeVariable(R) defined in kotlin

运行gradlew dependencyInsight --dependency org.springframework.security:spring-security-config - -configuration runtimeClasspath 给了我这个:

Welcome to Gradle 7.0!

Here are the highlights of this release:
 - File system watching enabled by default
 - Support for running with and building Java 16 projects
 - Native support for Apple Silicon processors
 - Dependency catalog feature preview

For more details see https://docs.gradle.org/7.0/release-notes.html

Starting a Gradle Daemon, 1 busy and 2 incompatible Daemons could not be reused, use --status for details

> Evaluating settings

> Task :dependencyInsight
org.springframework.security:spring-security-config:5.4.6 (selected by rule)
   variant "runtime" [
      org.gradle.status                  = release (not requested)
      org.gradle.usage                   = java-runtime
      org.gradle.libraryelements         = jar
      org.gradle.category                = library

      Requested attributes not found in the selected variant:
         org.gradle.dependency.bundling     = external
         org.gradle.jvm.environment         = standard-jvm
         org.jetbrains.kotlin.platform.type = jvm
         org.gradle.jvm.version             = 8
   ]

org.springframework.security:spring-security-config:5.4.6
+--- org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.4.5
|    \--- runtimeClasspath
\--- org.springframework.boot:spring-boot-starter-security:2.4.5
     \--- runtimeClasspath

(*) - dependencies omitted (listed previously)

A web-based, searchable dependency report is available by adding the --scan option.

BUILD SUCCESSFUL in 21s
1 actionable task: 1 executed

【问题讨论】:

  • 一个好的起点是确保您使用的是您期望的 Spring Security 版本。尝试运行 ./gradlew dependencyInsight --dependency org.springframework.security:spring-security-config --configuration runtimeClasspath 以查看是否有其他依赖项覆盖它。
  • @EleftheriaStein-Kousathana 我运行了命令并用结果编辑了我的问题,似乎spring-security-config 只有一个版本,即 5.4.6
  • 尝试使用等效的非 lambda 配置 oauth2ResourceServer().jwt().decoder(jwtDecoder()) 看看它是否有任何改变。我还注意到您使用的是 Gradle 7。Spring 团队使用的是 Gradle 6,可能存在与 Gradle 7 不兼容的一些功能。尝试使用 Gradle 6.8.3 看看是否有帮助。
  • 这似乎可行,但现在我遇到了 JUnit 测试类的问题,我根本没有修改它们,似乎找不到注释,我应该添加在我的 gradle 构建中对它们的依赖?在添加安全配置和依赖项之前,我运行我的项目没有任何问题。还更改了我的 gradle 版本,即使我没有更改它似乎也很好。
  • 别在意我之前的评论,当我更新 Spring Boot 版本并忘记对测试类做同样的事情时,我的错误。该项目现在构建并运行,没有任何错误。非常感谢您的帮助。

标签: spring spring-boot kotlin spring-security


【解决方案1】:

使用 lambda 版本解决了用户 Eleftheria Stein-Kousathana 建议的问题:

oauth2ResourceServer().jwt().decoder(jwtDecoder())

【讨论】:

    猜你喜欢
    • 2021-02-07
    • 2017-04-13
    • 2018-08-29
    • 2015-05-14
    • 2022-08-03
    • 2019-08-08
    • 2018-05-17
    • 2013-12-21
    • 2018-04-14
    相关资源
    最近更新 更多