Spring Cloud Gateway + keycloak возвращает 404 (не найдено) - PullRequest
0 голосов
/ 04 августа 2020

Я настраиваю микросервисную архитектуру с помощью весенней загрузки. Следовательно, у меня есть микросервис «po c -be», «api-gateway» и работающий экземпляр Keycloak для управления аутентификацией и авторизацией.
Я много искал и следовал различным примерам, но я ' m по-прежнему выдает ошибку 404 при вызове службы через api-gateway.
Keycloak
keycloak работает на localhost: 8080, я создал область, клиента, пользователя и роль : enter image description here

Using Postman, I can obtain an access token calling http://localhost:8080/auth/realms/my_realm/protocol/openid-connect/token Postman call for getting access 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.

...