Spring Cloud Gateway + keycloak возвращает 404 (не найдено)

Я настраиваю микросервисную архитектуру с помощью весенней загрузки. Следовательно, у меня есть poc-be микросервиса, api-gateway и работающий экземпляр Keycloak для управления аутентификацией и авторизацией.
Я много искал и следовал различным примерам, но все еще получаю ошибку 404, когда вызов службы через API-шлюз.
Keycloak
keycloak запущен на localhost: 8080, я создал область, клиента, пользователя и роль:  введите описание изображения  здесь

Используя Postman, я могу получить токен доступа по адресу http: // localhost: 8080 / auth / realms / my_realm / protocol / openid-connect / token  Вызов почтальона для получения токена доступа

Я бы использовал этот токен jwt для еще одного вызова API-шлюза для доступа к защищенной службе.
Шлюз API
Проект шлюза API имеет следующие соответствующие зависимости:

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.keycloak.bom</groupId>
                <artifactId>keycloak-adapter-bom</artifactId>
                <version>11.0.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <dependencies>
      <!-- Gateway functionality -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- keycloak Spring Boot Adapter -->
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>

Я настраиваю эту конфигурацию в 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/*

Вы можете увидеть маршрут для обращения к сервису (в данный момент сервис не обнаружен). Я реализовал класс SecurityConfig, как показано в руководствах:

@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

Но я не могу заставить шлюз api работать как со службой, так и с клавиатурой. Если я вызываю localhost: 8082 / api / hello / secure, передав токен доступа в качестве заголовка авторизации, я получаю 404 и не могу понять почему:  Шлюз API 404

Читая журналы, я вижу, что происходит процесс аутентификации, но я не могу объяснить ошибку 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.


person Cirux    schedule 04.08.2020    source источник
comment
Вы решили эту проблему?   -  person Vivek Runwal    schedule 03.07.2021


Ответы (1)


По-видимому, как показано в журнале запуска приложения, Spring MVC прямо сейчас несовместим со Spring Cloud Gateway (версия Hoxton.SR8), это сообщение в журнале:

Spring MVC обнаружен в пути к классам, что в настоящее время несовместимо со Spring Cloud Gateway. Удалите зависимость spring-boot-starter-web.

Ваша зависимость keycloak-spring-boot-starter включает spring-boot-starter-web

person nneesstt    schedule 10.09.2020