Spring security WebFlux "Найдено несколько токенов на предъявителя в запросе" - PullRequest
0 голосов
/ 05 июля 2019

Я создаю угловое приложение (чат), которое подключается к Keycloak с angular-oauth2-oidc и вызывает бэкэнд spring boot WebFlux как SecurityRessourceServer для получения и отправки сообщений. Когда пользователь входит в приложение, сервис вызывает, чтобы получить некоторые исторические сообщения, а сервис sse вызывает. С первым GET у меня не было никаких проблем. Маркер-носитель хорошо отправляется в заголовке «Авторизация» и работает нормально. Но для SSE (с классическим источником событий). Маркер не может быть передан как заголовок, но как переменная пути (access_token, как рекомендовано OAuth), но Spring Security не перехватил его и вернул 401.

Чтобы исправить эту проблему, я добавил фильтр, который ловит токен в URI и вставляет его в качестве заголовка. И что удивительно, теперь весенняя загрузка ответила 500 сообщением: «В запросе найдено несколько токенов на предъявителя».

Я попытался изменить имя переменной пути на «tok», и теперь оно работает нормально. Поэтому я понимаю, что Spring хорошо ловит токен в URL с именем access_token, но не очень хорошо. Возможно, это неправильная конфигурация?

Конфигурация безопасности Spring с фильтром:

@Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .csrf().disable()
                .addFilterAt((WebFilter) (exchange, chain) -> {
                    ServerHttpRequest request = exchange.getRequest();
                    if(HttpMethod.GET.equals(request.getMethod()) && request.getQueryParams().getFirst("access_token")!=null) {
                        exchange.getRequest().mutate().headers(httpHeaders ->
                                httpHeaders.add(
                                    "Authorization",
                                    request.getQueryParams().getFirst("access_token"))
                        );
                    }
                    return chain.filter(exchange);
                }, SecurityWebFiltersOrder.FIRST)
                .authorizeExchange()
                .pathMatchers(HttpMethod.OPTIONS ,"/**").permitAll()
                .anyExchange().authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt();
        return http.build();
    }

И вызов EventSource:

const accessToken = 'Bearer ' + this.oauthService.getAccessToken();
    const eventSource = new EventSource(
      this.baseUrl + '/messages/subscribe?travelId=cb223637-9290-43e3-a096-2226fab67ee0&access_token=' + accessToken
    );

У вас есть идея? Заранее спасибо.

...