16

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

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

Это можно суммировать по приведенной ниже схеме: Security Architecture

  1. Клиент первой аутентификации с IDP (OpenID Connect/OAuth2)
  2. ВПЛ возвращает маркер доступа (непрозрачный маркер без каких-либо информации о пользователе)
  3. клиента делает вызов через шлюз API использовать маркер доступа в авторизации заголовке
  4. шлюз по API делает запрос к МВУ с маркерами доступа
  5. IDP проверяет, что токен доступа действителен и возвращает информацию о пользователе в формате JSON.
  6. Шлюз API хранит информацию пользователя в JWT и подписывает ее с помощью закрытого ключа. JWT затем передается вниз по течению службы, которая подтверждала JWT с использованием открытого ключа
  7. Если служба должна вызвать другую услугу, чтобы выполнить запрос, он проходит в JWT, вдоль которой служит аутентификации и авторизации для запроса

То, что я до сих пор

у меня есть большинство, что сделано с помощью:

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

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

Проблема

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

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

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

+0

Почему вы не используете Spring Cloud Security для этого? который предоставляет этот готовый вариант для afaik. –

+0

@ M.Deinum Я не думал, что у меня хватит сил для реализации этого конкретного дизайна. Мне нужно иметь токен доступа за пределами моей защищенной сети и JWT внутри. У меня нет большого опыта в безопасности Spring Cloud. Как вы думаете, я могу использовать его для достижения моего дизайна? – phoenix7360

+0

Spring Cloud Security только передает тот же токен сервисам нисходящего потока. У него нет возможности обменивать или увеличивать токены, как это делает @ phoenix7360. Тем не менее, это разумный строительный блок для работы. –

ответ

9

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

0

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

//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 для текущего запроса активных потоков. и вы можете предоставить код статуса ответа.

3

Добавьте следующее в вашем методе выполнения, он будет решать эту проблему

ctx.setSendZuulResponse(false); 
ctx.setResponseStatusCode(401); 
Смежные вопросы