Класс SpringOpaqueTokenIntrospector не найден

Я столкнулся с некоторыми проблемами во время работы Spring Boot 2.7.0 и spring-boot-starter-oauth2-resource-server. Моя цель — использовать Keycloak для проверки токенов из http-запросов. Но поскольку я добавил spring-boot-starter-oauth2-resource-server в свое приложение, оно не запускается из-за исключения:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerOpaqueTokenConfiguration$OpaqueTokenIntrospectionClientConfiguration': Lookup method resolution failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerOpaqueTokenConfiguration$OpaqueTokenIntrospectionClientConfiguration] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@6f94fa3e]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:289)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1302)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1219)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
    at com.test.TestApplication.main(TestApplication.java:14)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.IllegalStateException: Failed to introspect Class [org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerOpaqueTokenConfiguration$OpaqueTokenIntrospectionClientConfiguration] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@6f94fa3e]
    at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:485)
    at org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:321)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:267)
    ... 23 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/security/oauth2/server/resource/introspection/SpringOpaqueTokenIntrospector
    at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3402)
    at java.base/java.lang.Class.getDeclaredMethods(Class.java:2504)
    at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:467)
    ... 25 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.security.oauth2.server.resource.introspection.SpringOpaqueTokenIntrospector
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    ... 29 common frames omitted


Process finished with exit code 0

Зависимости проекта:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-jose</artifactId>
</dependency>

Вы хоть представляете, что не так с этой настройкой? заранее спасибо

Каково ваше намерение? Создание сервера Keycloak в приложении Spring Boot 2 или использование OAuth2 для защиты запросов к вашему приложению Spring Boot 2? Первое смотрите здесь , а второе смотрите там.

kladderradatsch 08.11.2022 15:21
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
141
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, если ваш сервер авторизации создает JWT (Keycloak делает), вам, вероятно, лучше использовать декодер JWT, чем самоанализ токена. Это намного эффективнее: все JWT проверяются с помощью открытого ключа, загружаемого только один раз, когда для самоанализа требуется, чтобы ресурс-сервер (Spring REST API) отправлял каждый токен доступа на сервер авторизации (Keycloak).

Во-вторых, дважды проверьте версию spring-security-oauth2-resource-server в вашем дереве зависимостей: SpringOpaqueTokenIntrospector есть только с 5.6.

В-третьих, я предложил более простой способ сопоставления полномочий для самоанализа токенов в версии 5.8: предоставьте преобразователь аутентификации (обработайте результат самоанализа) вместо перегрузки всего интроспектора:

http.oauth2ResourceServer().opaqueToken().authenticationConverter(authenticationConverter);

где authenticationConverter можно реализовать как:

(String introspectedToken, OAuth2AuthenticatedPrincipal authenticatedPrincipal) -> new BearerTokenAuthentication(
            authenticatedPrincipal,
            new OAuth2AccessToken(
                    OAuth2AccessToken.TokenType.BEARER,
                    introspectedToken,
                    authenticatedPrincipal.getAttribute(OAuth2TokenIntrospectionClaimNames.IAT),
                    authenticatedPrincipal.getAttribute(OAuth2TokenIntrospectionClaimNames.EXP)),
            authoritiesConverter.convert(authenticatedPrincipal.getAttributes()));

а authoritiesConverter — это Converter<Map<String, Object>, Collection<? extends GrantedAuthority>> (сопоставляет авторитеты из ответа Keycloak самоанализа JSON, который вы уже должны были реализовать)

Наконец, вы можете найти полезные советы по настройке вашего сервера ресурсов в этом руководстве: это может быть так же просто, как

        <dependency>
            <groupId>com.c4-soft.springaddons</groupId>
            <!-- change "webmvc" with "webflux" for reactive apps -->
            <!-- change "jwt" with "introspecting" for access-token introspection instead of JWT decoding -->
            <artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
            <!-- 6.0.4 goes with spring-boot 3.0.0-RC1, use 5.x with boot 2.6.x and below -->
            <version>6.0.4</version>
        </dependency>
@EnableMethodSecurity
@Configuration
public class SecurityConfig { }
spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://localhost:8443/realms/master/protocol/openid-connect/token/introspect
spring.security.oauth2.resourceserver.opaquetoken.client-id=spring-addons-confidential
spring.security.oauth2.resourceserver.opaquetoken.client-secret=change-me

com.c4-soft.springaddons.security.issuers[0].location=https://localhost:8443/realms/master

# shoud be configured with a list of private-claims this authorization-server puts user roles into
# below is default Keycloak conf for a `spring-addons` client with client roles mapper enabled
com.c4-soft.springaddons.security.issuers[0].authorities.claims=realm_access.roles,resource_access.spring-addons-public.roles,resource_access.spring-addons-confidential.roles

# Fine-grained CORS configuration can be set per path as follow:
com.c4-soft.springaddons.security.cors[0].path=/sample/**

# More useful resource-server security conf from preperties, use IDE auto-completion

Другие вопросы по теме