Запрос веб-сокета не направляется через глобальный фильтр шлюза

Проблема

Я установил глобальный фильтр для всех запросов, который добавляет информацию о пользователе в заголовки. Этот фильтр работает для всех моих http-запросов, но не применяет их к моим запросам веб-сокетов.

Вопросов

  • Проходят ли запросы веб-сокетов через GlobalFilters?
  • Если запросы веб-сокетов не проходят через GlobalFilters, есть ли способ указать фильтр для веб-сокетов?
  • Существуют ли какие-либо подходы, которые позволят мне вводить информацию о пользователе в запросы веб-сокетов через spring-cloud-gateway?

Настраивать

Конфигурация шлюза

    gateway:
      routes:
        - id: example
          uri: http://localhost:80
          predicates:
            - Path=/example/**
          filters:
            - RewritePath=/example/(?<path>.*), /$\{path}

Глобальный фильтр

@Component
class CustomGlobalFilter(private val jwtDecoder: ReactiveJwtDecoder) : GlobalFilter {
    private val logger = KotlinLogging.logger {}

    /**
     * Given exchange, extract Authorization header value and modify to retrieve JWT token.
     */
    fun extractJwtToken(exchange: ServerWebExchange): String {
        return (exchange.request.headers["Authorization"]
            ?: throw JwtExtractionException("Request does not contain Authorization header"))[0]
            .replace("Bearer ", "")
    }

    /**
     * Modify request headers to add `username`.
     */
    fun modifyHeaders(exchange: ServerWebExchange): Mono<ServerWebExchange> {
        return try {
            val jwt = extractJwtToken(exchange)

            jwtDecoder
                .decode(jwt)
                .map {
                    val username = it.claims["username"] as String

                    val modRequest = exchange
                        .request
                        .mutate()
                        .header("username", username)
                        .build()

                    exchange.mutate()
                        .request(modRequest)
                        .build()
                }
        } catch (e: JwtExtractionException) {
            exchange.toMono() // fall back on default exchange
        }
    }

    /**
     * Filter all outgoing requests to modify headers.
     */
    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        return modifyHeaders(exchange)
            .flatMap { chain.filter(it) }
    }
}

0
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мне удалось решить проблему маршрутизации, установив пользовательский порядок фильтров перед WebsocketRoutingFilter

@Component
class CustomGlobalFilter(
        private val authFilterUtil: AuthFilterUtil,
) : GlobalFilter, Ordered {

    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        return authFilterUtil
                .modifyHeaders(exchange)
                .flatMap { chain.filter(it) }
    }

    override fun getOrder(): Int {
        return Ordered.HIGHEST_PRECEDENCE
    }
}

Другие вопросы по теме