Я настраиваю микросервисную архитектуру с помощью весенней загрузки. Следовательно, у меня есть микросервис «po c -be», «api-gateway» и работающий экземпляр Keycloak для управления аутентификацией и авторизацией.
Я много искал и следовал различным примерам, но я ' m по-прежнему выдает ошибку 404 при вызове службы через api-gateway.
Keycloak
keycloak работает на localhost: 8080, я создал область, клиента, пользователя и роль :
Using Postman, I can obtain an access token calling http://localhost:8080/auth/realms/my_realm/protocol/openid-connect/token
I would use this jwt token for making another call to the api-gateway for accessing protected service.
API gateway
The api gateway project has the following relevant dependencies:
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.keycloak.bom
keycloak-adapter-bom
11.0.0
pom
import
<!-- Gateway functionality -->
org.springframework.cloud
spring-cloud-starter-gateway
<!-- keycloak Spring Boot Adapter -->
org.keycloak
keycloak-spring-boot-starter
org.springframework.boot
spring-boot-starter-security
I setup this configuration in application-dev.yml
server:
port: 8082
cluster:
uri-local-be: http://localhost:8083
keycloak:
enabled: true
realm: my_realm
# The value we specify in keycloak.resource matches the client we named in the admin console
resource: niuma-services
auth-server-url: http://localhost:8080/auth
bearer-only: true
principal-attribute: preferred_username
public-client: true
spring:
...
cloud:
gateway:
routes:
- id: protected
uri: ${cluster.uri-local-be}
predicates:
- Path=/api/hello/*
You can see the route for addressing the service (no service discovery at the time).
I implemented a SecurityConfig class, as found on tutorials:
@Configuration
@EnableWebSecurity(debug = true)
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
@Slf4j
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
log.info("SecurityConfig.configureGlobal");
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
log.info("SecurityConfig.KeycloakConfigResolver");
return new KeycloakSpringBootConfigResolver();
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
log.info("SecurityConfig.sessionAuthenticationStrategy");
return new NullAuthenticatedSessionStrategy();
}
@Bean
public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
KeycloakAuthenticationProcessingFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Bean
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(KeycloakPreAuthActionsFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
log.info("SecurityConfig.configure");
super.configure(http);
http.authorizeRequests().antMatchers("/spi*").hasRole("user").anyRequest().permitAll();
}
@Bean
public ServerCodecConfigurer serverCodecConfigurer() {
return ServerCodecConfigurer.create();
}
The microservice it's exposing an endpoint at localhost:8083/api/hello/secure returning a simple string.
I achieved the desired behavior when calling directly localhost:8083/api/hello/secure/ :
- unhauthorized when calling without access token
- successfully respond when calling with access token
But I can't get the api gateway working with both the service and keycloak.
If I call localhost:8082/api/hello/secure passing the access token as Authorization header, I get a 404 and I can't understand why:
404 API-шлюз
Чтение журналов Я вижу, что происходит процесс аутентификации, но я не могу объяснить 404:
o.s.security.web.FilterChainProxy : /error at position 1 of 15 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
o.s.security.web.FilterChainProxy : /error at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@7102dd3c: Authentication: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@7102dd3c: Principal: ciro; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@42a60ed1; Granted Authorities: ROLE_offline_access, ROLE_user, ROLE_uma_authorization'
...
o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/sso/login']
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/sso/login'
...
f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
o.k.a.BearerTokenRequestAuthenticator : Found [1] values in authorization header, selecting the first value for Bearer.
...
o.k.a.BearerTokenRequestAuthenticator : successful authorized
o.k.adapters.RequestAuthenticator : User 'ciro' invoking 'http://localhost:8082/error' on client 'niuma-services'
...
o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet'
...
o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 404, headers={masked}
...
Надеясь, что я сообщил всю необходимую информацию, я бы попросил некоторую помощь в получении аутентификация работает с использованием токена доступа, полученного из keycloak, вызывая шлюз API.