В настоящее время я выполняю миграцию из Spring Security OAuth2 в Keycloak (после решения команды Spring Security об отказе от поддержки проекта Spring Security OAuth2), но я застрял с этим исключением:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalStateException: permitAll only works with HttpSecurity.authorizeRequests()
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:656)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:484)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$330.00000000ED7F64A0.getObject(Unknown Source)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
У меня есть 10 микросервисов для мигрировать, я определил common
банку, которая содержит все конфигурации. Это конфигурация Keycloak в common
:
@EnableGlobalMethodSecurity( prePostEnabled = true, securedEnabled = true )
@KeycloakConfiguration
@Import( KeycloakSpringBootConfigResolver.class )
public class CommonsKeycloakSecurityConfigurerAdapter extends KeycloakWebSecurityConfigurerAdapter {
@Override
protected void configure( HttpSecurity http ) throws Exception {
http.oauth2ResourceServer(); // Equivalent to @EnableResourceServer in S.S. OAuth2
super.configure( http );
}
@Autowired
public void configureGlobal( AuthenticationManagerBuilder auth ) {
SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
grantedAuthorityMapper.setPrefix( "ROLE_" );
grantedAuthorityMapper.setConvertToUpperCase( true );
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper( grantedAuthorityMapper );
auth.authenticationProvider( keycloakAuthenticationProvider );
}
@Value("${spring.application.name}"
public String APP_NAME;
@Bean
public SessionAuthenticationStrategy sessionAuthenticationStrategyPorvider() {
return APP_NAME.equals( "securityservice")
? new RegisterSessionAuthenticationStrategy( new SessionRegistryImpl() )
: new NullAuthenticatedSessionStrategy();
}
@Bean
@DependsOn( "sessionAuthenticationStrategyPorvider" )
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return sessionAuthenticationStrategyPorvider();
}
@Bean
@Scope( scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS )
public KeycloakSecurityContext provideKeycloakSecurityContext() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
Principal principal = requireNonNull( attributes ).getRequest().getUserPrincipal();
if ( principal == null ) {
return null;
}
if ( principal instanceof KeycloakAuthenticationToken ) {
principal = (Principal) ( (KeycloakAuthenticationToken) principal ).getPrincipal();
}
if ( principal instanceof KeycloakPrincipal ) {
return ( (KeycloakPrincipal) principal ).getKeycloakSecurityContext();
}
return null;
}
}
И свойства в common/src/main/resources/application.yml
:
keycloak:
auth-server-url: "" #defined in application-dev.yml and application-prod.yml
realm: ${project.name}
resource: ${spring.application.name}
credentials:
secret: ${application.kck.secret}
use-resource-role-mappings: true
ssl-required: 'none'
principal-attribute: preferred_username
common.jar
затем импортируется в все остальные микросервисы. В productservice
я определил эти конкретные правила безопасности http:
@Configuration
@Order( 1 )
public class UIResourceProtection extends WebSecurityConfigurerAdapter { // Note that I use WebSecurityConfigurerAdapter instead of KeycloakWebSecurityConfigurerAdapter
@Override
public void configure( HttpSecurity http ) throws Exception {
http.sessionManagement().sessionCreationPolicy( STATELESS );
http.requestMatchers().antMatchers( "/ui/product/**" )
.and()
.cors().and()
.authorizeRequests()
.antMatchers( "/ui/product/private").hasRole( "USER" )
.antMatchers( HttpMethod.PUT, "/ui/product/public" ).hasRole( "USER" )
.antMatchers( HttpMethod.GET, ""/ui/product/cost"","/ui/product/public").authenticated()
.antMatchers( HttpMethod.GET, "/ui/product/public/{id}" ).authenticated()
.antMatchers( "/ui/product/public/dashboard" ).hasRole( "USER" );
}
}
И еще один в том же проекте (т. Е. productservice
)
@Configuration
@RequiredArgsConstructor
@Order( 2 )
public class SelfResourceProtection extends WebSecurityConfigurerAdapter { // Note that I use WebSecurityConfigurerAdapter instead of KeycloakWebSecurityConfigurerAdapter
@Override
public void configure( HttpSecurity http ) throws Exception {
http.requestMatchers().antMatchers("/product/**")
.and()
.authorizeRequests()
.antMatchers( HttpMethod.GET, "/product/update-db" ).hasRole( "ADMIN" )
.antMatchers( HttpMethod.GET, "/product/private/{id}" ).permitAll();
}
}
Когда я запускаю productservice
с этой конфигурацией у меня есть исключение выше: Caused by: java.lang.IllegalStateException: permitAll only works with HttpSecurity.authorizeRequests()
После изменения параметров конфигурации исключение по-прежнему выдается.
Есть идеи, как ее решить?
Версия зависимостей:
Spring Boot : 2.2.4.RELEASE
Keycloak : 8.0.1
Spring Security: 5.2.1.RELEASE
Spring Security OAuth2 Resource Server: 5.2.1.RELEASE
Большое спасибо