在Spring云网关和Spring Security中运行本机映像时出现Kotlin.reflect.jvm.internal. kotlin反射内部错误

8yparm6h  于 2023-01-05  发布在  Spring
关注(0)|答案(1)|浏览(234)

我已经成功地生成了在Kotlin中实现的Spring Cloud Gateway(2022.0.0 - Sping Boot 3.0.0)应用程序的本机映像。
我有以下安全配置:

@EnableReactiveMethodSecurity
@Configuration(proxyBeanMethods = false)
class SecurityConfiguration(private val clientService: ClientService,
                            private val env: Environment) {

    @Bean
    fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
        return http.requestCache {
            it.requestCache(NoOpServerRequestCache.getInstance())
        }.headers { headers ->
            headers.frameOptions { frameOptions ->
                frameOptions.disable()
            }
        }.csrf { it.disable() }
                .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
                .addFilterAt(basicAuthenticationFilter(), SecurityWebFiltersOrder.HTTP_BASIC)
                .authorizeExchange()
                .pathMatchers("/actuator/health").permitAll()
                ...
                .and()
                .build()
    }

    @Bean
    fun passwordEncoder(): PasswordEncoder {
        return createDelegatingPasswordEncoder()
    }

    private fun basicAuthenticationFilter(): AuthenticationWebFilter {
        val authManager = ApiAuthenticationManager(clientService)
        val apiAuthenticationFilter = AuthenticationWebFilter(authManager)
        return apiAuthenticationFilter
    }

}

当我运行本机映像时,它崩溃,并出现以下异常:

kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Could not compute caller for function: private open fun basicAuthenticationFilter(): org.springframework.security.web.server.authentication.AuthenticationWebFilter defined in xxx.configuration.SecurityConfiguration[DeserializedSimpleFunctionDescriptor@3ff718f] (member = null)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:88)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:61)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:63)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
        at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt:61)
        at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:63)
        at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:136)
        at org.springframework.core.MethodParameter$KotlinDelegate.getGenericReturnType(MethodParameter.java:914)
        at org.springframework.core.MethodParameter.getGenericParameterType(MethodParameter.java:510)
        at org.springframework.core.SerializableTypeWrapper$MethodParameterTypeProvider.getType(SerializableTypeWrapper.java:291)
        at org.springframework.core.SerializableTypeWrapper.forTypeProvider(SerializableTypeWrapper.java:107)
        at org.springframework.core.ResolvableType.forType(ResolvableType.java:1413)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1334)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1316)
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1283)
        at org.springframework.core.ResolvableType.forMethodReturnType(ResolvableType.java:1228)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:814)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:681)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:652)
        at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1632)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:559)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:531)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:106)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:745)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:565)
        at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291)
        at xxx.GatewayApplicationKt.main(GatewayApplication.kt:27)

Exception in thread "main" kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Could not compute caller for function: private open fun basicAuthenticationFilter(): org.springframework.security.web.server.authentication.AuthenticationWebFilter defined in xxx.configuration.SecurityConfiguration[DeserializedSimpleFunctionDescriptor@3ff718f] (member = null)

这个调用.addFilterAt(basicAuthenticationFilter(), SecurityWebFiltersOrder.HTTP_BASIC),引用了一个私有函数,似乎涉及到某种Kotlin反射。
有什么办法解决这个问题吗?

arknldoa

arknldoa1#

Spring Security使用反射来获取自定义过滤器的类,以便跟踪过滤器链中的顺序。
要将代码作为本机映像运行,需要一个反射提示来告诉GraalVM私有方法basicAuthenticationFilter需要在本机映像中可用。
可以使用RuntimeHintsRegistrar添加自定义提示。在这种情况下,可以使用以下命令注册basicAuthenticationFilter以进行反射:

public class MyRuntimeHints implements RuntimeHintsRegistrar {

    @Override
    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
        Method method = ReflectionUtils.findMethod(SecurityConfiguration.class, "basicAuthenticationFilter"
        hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
    }

}

相关问题