Подтвердить что ты не робот

Использование Zuul в качестве шлюза аутентификации

Фон

Я хочу реализовать проект, представленный в этой статье .

Это можно резюмировать на диаграмме ниже: Архитектура безопасности

  • Клиент сначала выполняет аутентификацию с помощью IDP (OpenID Connect/OAuth2)
  • IDP возвращает токен доступа (непрозрачный токен без информации пользователя)
  • Клиент делает вызов через шлюз API, используя токен доступа в заголовке авторизации
  • Шлюз API делает запрос к IDP с помощью токена доступа
  • IDP проверяет, что токен доступа действителен и возвращает пользовательскую информацию в формате JSON.
  • Шлюз API хранит информацию пользователя в JWT и подписывает ее с помощью закрытого ключа. Затем JWT передается в службу нисходящего потока, которая проверяет JWT с использованием открытого ключа
  • Если служба должна вызывать другую службу для выполнения запроса, она передает JWT, по которому выполняется аутентификация и авторизация для запроса.

Что я до сих пор

У меня больше всего сделано, используя:

  • Spring облако как глобальная структура
  • Spring для запуска отдельных служб
  • Netflix Zuul как шлюз API

Я также написал фильтр Zuul PRE, который проверяет токен доступа, связывается с IDP и создает JWT. Затем JWT добавляется в заголовок для запроса, перенаправленного в нисходящую службу.

Проблема

Теперь мой вопрос весьма специфичен для Zuul и его фильтров. Если по какой-либо причине аутентификация не удалась в шлюзе API, как я могу остановить маршрутизацию и ответить напрямую с помощью 401, не продолжая цепочку фильтров и переадресацию вызова?

В настоящий момент, если аутентификация завершается неудачей, фильтр не добавит JWT в заголовок, а 401 будет поступать из нисходящей службы. Я надеялся, что мой шлюз может предотвратить этот ненужный звонок.

Я попытался понять, как использовать com.netflix.zuul.context.RequestContext для этого, но документация довольно плохая, и я не мог найти способ.

4b9b3361

Ответ 1

Вы можете попробовать установить setSendZuulResponse(false) в текущем контексте. Это не должно направлять запрос. Вы также можете вызвать removeRouteHost() из контекста, который достигнет того же. Вы можете использовать setResponseStatusCode для установки кода состояния 401.

Ответ 2

Добавьте в свой метод run следующее: он решит эту проблему

ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);

Ответ 3

Я знаю, что очень поздно ответить Вы можете подойти с предварительным фильтром зуула. Ниже приведены шаги, которые вы должны выполнить.

 //1. create filter with type pre
 //2. Set the order of filter to greater than 5 because we need to run our filter after preDecoration filter of zuul.
 @Component
 public class CustomPreZuulFilter extends ZuulFilter {

  private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public Object run() {
    final RequestContext requestContext = RequestContext.getCurrentContext();
    logger.info("in zuul filter " + requestContext.getRequest().getRequestURI());
    byte[] encoded;
    try {
        encoded = Base64.encode("fooClientIdPassword:secret".getBytes("UTF-8"));
        requestContext.addZuulRequestHeader("Authorization", "Basic " + new String(encoded));

        final HttpServletRequest req = requestContext.getRequest();
        if (requestContext.getRequest().getHeader("Authorization") == null
                && !req.getContextPath().contains("login")) {
            requestContext.unset();
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());

        } else {
              //next logic
            }
        }

    } catch (final UnsupportedEncodingException e) {
        logger.error("Error occured in pre filter", e);
    }

    return null;
}



@Override
public boolean shouldFilter() {
    return true;
}

@Override
public int filterOrder() {
    return 6;
}

@Override
public String filterType() {
    return "pre";
}

}

requestContext.unset() сбрасывает RequestContext для текущего запроса активных потоков. и вы можете предоставить код статуса ответа.