Я хочу защитить свое приложение 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.
Я понимаю, почему это проблема. Вопрос в том, как я могу предотвратить это или исправить мой конфликт?
Шаги, которые я сделал до сих пор:
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




Похоже, что есть ошибка в интеграции Keycloak Spring Security, которая означает, что приложение, являющееся подклассом KeycloakWebSecurityConfigurerAdapter, попытается создать два bean-компонента с именем httpSessionManager. Когда два bean-компонента определены с одним и тем же именем, второе обнаруженное определение будет пытаться переопределить первое. Это переопределение запрещено по умолчанию в Spring Boot 2.1. Я бы рекомендовал сообщить об этом как об ошибке интеграции Keycloak Spring Security. Пока вы ждете исправления ошибки, вы можете обойти проблему, установив spring.main.allow-bean-definition-overriding=true в application.properties.
Это помогло мне решить проблему, удалить @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.
Я использую 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
Спасибо, что помогли мне найти проблему (КЛЮЧ-8725).