Невозможно использовать Keycloak в Spring Boot 2.1 из-за дублированной регистрации bean-компонентов httpSessionManager

Я хочу защитить свое приложение Spring Boot 2.1 с помощью Keycloak 4.5.

В настоящее время я не могу запустить приложение из-за следующей ошибки:

Exception encountered during context initialization - cancelling refresh attempt: 
org.springframework.beans.factory.support.BeanDefinitionOverrideException: 
  Invalid bean definition with name 'httpSessionManager' defined in class path resource [dummy/service/SecurityConfig.class]: 
    Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=securityConfig; factoryMethodName=httpSessionManager; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [dummy/SecurityConfig.class]] for bean 'httpSessionManager': 
There is already [Generic bean: class [org.keycloak.adapters.springsecurity.management.HttpSessionManager]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in URL [jar:file:/.m2/repository/org/keycloak/keycloak-spring-security-adapter/4.5.0.Final/keycloak-spring-security-adapter-4.5.0.Final.jar!/org/keycloak/adapters/springsecurity/management/HttpSessionManager.class]] bound.

Мой класс SecurityConfig (см. Ниже) расширяется от KeycloakWebSecurityConfigurerAdapter. Этот адаптер уже определяет bean-компонент httpSessionManager.

Я понимаю, почему это проблема. Вопрос в том, как я могу предотвратить это или исправить мой конфликт?

Шаги, которые я сделал до сих пор:

  • Построил мой помпон (см. Ниже), используя:
    • Spring-Boot-Starter-Web
    • пружина-загрузчик-стартер-безопасность
    • ключ-пружина-загрузчик-стартер
    • keycloak-adapter-bom в dependencyManagement
  • Определил собственный SecurityConfig, расширяющий KeycloakWebSecurityConfigurerAdapter

pom.xml

...
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.0.RELEASE</version>
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

    <java.version>11</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>

    <keycloak.version>4.5.0.Final</keycloak.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.keycloak.bom</groupId>
            <artifactId>keycloak-adapter-bom</artifactId>
            <version>${keycloak.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
...

SecurityConfig.java

@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Import(KeycloakWebSecurityConfigurerAdapter.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.csrf().ignoringAntMatchers("/**/*");
        http.authorizeRequests()
                .anyRequest().permitAll();
    }
}

Обновлять Есть известная проблема (КЛЮЧ-8725). Исправление запланировано на 5.x Keycloak. Однако в комментариях есть обходной путь. Просто замените аннотацию @KeyCloakConfiguration на:

@Configuration
@ComponentScan(
    basePackageClasses = KeycloakSecurityComponents.class,
    excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.keycloak.adapters.springsecurity.management.HttpSessionManager"))
@EnableWebSecurity
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
38
0
13 758
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

Похоже, что есть ошибка в интеграции Keycloak Spring Security, которая означает, что приложение, являющееся подклассом KeycloakWebSecurityConfigurerAdapter, попытается создать два bean-компонента с именем httpSessionManager. Когда два bean-компонента определены с одним и тем же именем, второе обнаруженное определение будет пытаться переопределить первое. Это переопределение запрещено по умолчанию в Spring Boot 2.1. Я бы рекомендовал сообщить об этом как об ошибке интеграции Keycloak Spring Security. Пока вы ждете исправления ошибки, вы можете обойти проблему, установив spring.main.allow-bean-definition-overriding=true в application.properties.

Спасибо, что помогли мне найти проблему (КЛЮЧ-8725).

Tobias Bertram-Köhler 15.11.2018 13:22

Это помогло мне решить проблему, удалить @KeycloakConfiguration и использовать вместо этого (из КЛЮЧ-8725):

Ява:

@Configuration
@ComponentScan(
        basePackageClasses = KeycloakSecurityComponents.class,
        excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.keycloak.adapters.springsecurity.management.HttpSessionManager"))
@EnableWebSecurity

Котлин:

@Configuration
@ComponentScan(
    basePackageClasses = [KeycloakSecurityComponents::class],
    excludeFilters = [ComponentScan.Filter(type = FilterType.REGEX, pattern = ["org.keycloak.adapters.springsecurity.management.HttpSessionManager"])]
)
@EnableWebSecurity

Предпочтительный способ обратиться к повторяющемуся определению bean-компонента HttpSessionManager - переопределить создание этого bean-компонента в вашем SecurityConfig и добавить условную аннотацию к его экземпляру, как показано ниже:

@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Import(KeycloakWebSecurityConfigurerAdapter.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
    @Bean
    @Override
    @ConditionalOnMissingBean(HttpSessionManager.class)
    protected HttpSessionManager httpSessionManager() {
        return new HttpSessionManager();
    }
}

Это было полезно при работе с последним адаптером Keycloak 8.0 и Spring boot 2.

sunitkatkar 29.11.2019 03:45

Я использую keycloak-spring-security-adapter в версии 6.0.1. Решение по удалению @KeycloakConfiguration со специальной конфигурацией у меня не сработало.

Мое решение заключалось в том, чтобы добавить в application.properties следующую строку:

spring.main.allow-bean-definition-overriding: true

Лучший способ избавиться от этой ошибки с помощью git - исключить загрузку класса KeyCloakAutoCOnfiguration во время запуска Весенний ботинок.

Просто добавьте ниже в файл application.yaml

spring:
  autoconfigure:
    exclude: 
      org.keycloak.adapters.springboot.KeycloakAutoConfiguration

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