Проверка данных в разных микросервисах

Я уже прочитал множество тем об этом, но до сих пор не нашел лучшего подхода.

У меня User. Один User может иметь много Posts. Пользователи и сообщения - это микросервисы другой. Я использую Spring Boot.

Когда интерфейс вызывает мою микросервис Posts, отправляя запрос POST в /posts/user/1, мне нужно проверить, существует ли данный userId (1) в моей базе данных Users. Если нет, генерировать исключение, сообщающее клиентской части, что пользователь не существует. Если да, то вставьте данное тело запроса как Post.

Возникает вопрос: как мне проверить эту информацию на моем сервере? Мы не хотим перекладывать эту ответственность на внешний интерфейс, поскольку javascript является клиентским, и злоумышленник может обойти эту проверку.

Параметры:

  • Связь REST между микросервисами. (Публикует микросервис вызова микросервиса пользователей с вопросом, существует ли данный идентификатор на его стороне)
  • Предоставить микросервису Posts доступ к базе данных микросервиса пользователей

Я понимаю, что общение между ними создаст связь, но я не уверен, что предоставление доступа Post к базе данных пользователей является лучшим вариантом.

Не стесняйтесь предлагать любые варианты.

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

Yati Sawhney 12.09.2018 17:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
14
1
4 152
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

У вас есть возможность осуществлять межпроцессное взаимодействие между микросервисами Post и User с помощью подхода RESTful.

В случае, если вы просто хотите проверить наличие ресурса и не хотите, чтобы в ответ было какое-либо тело, вам следует использовать HTTP-метод HEAD. Поэтому ваша конечная точка API, размещенная на микросервисе User, будет выглядеть так:

HEAD  user/{userId}

Вызовите этот API из микросервиса Post.

Return 200 / OK if user exist

Return 404 / Not Found if user does not exist

кликните сюда и здесь, чтобы получить более подробную информацию об использовании метода HEAD и вариантах использования.

Вы правы, вы должны выполнить проверку на бэкэнде, поскольку, я полагаю, это служба REST, и запросы можно отправлять не только из пользовательского интерфейса.

Предположим, у вас есть реализация сервиса:

@Service
class UsersServiceImpl implements UsersService {

  private final Users users;

  public UsersServiceImpl(Users users) {
    this.users = users;
  }

  @Override
  public void addPost(long userId, Post post) {
    User user = users.get(userId);
    if (user == null) {
      throw new UserNonExistent(userId);
    }
    user.addPost(post);
  }
}

где Users - это интерфейс, представляющий базу данных пользователей, а UserNonExistent - это RuntimeException. Затем в вашем контроллере вы можете сделать следующее:

@RestController
class UsersController {

  private final UsersService usersService;

  public UsersController(UsersService usersService) {
    this.usersService = usersService;
  }

  @PostMapping("/posts/user/{userId}")
  public void addPostToUser(@PathVariable String userId, @RequestBody Post post) {
    usersService.addPost(userId, post);
  }

  @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "User does not exist")
  @ExceptionHandler({UsersService.UserNonExistent.class})
  public void handleUserNonExistentException() {
    // Nothing to do
  }
}

Если предоставленный ID пользователя недействителен, будет вызван метод handleUserNonExistentException(), который вернет код состояния HTTP ПЛОХОЙ ЗАПРОС.

Этот ответ предполагает, что сервер является монолитом, тогда как OP четко заявил, что вопрос касается микросервисов.

Sync 11.11.2018 17:45
Ответ принят как подходящий

Для этого очень конкретного случая использования, если у вас есть уровень безопасности, вы можете (должны) использовать токен доступа пользователя, чтобы гарантировать, что этот запрос обрабатывается для правильного пользователя, что может быть выполнено путем проверки токена и полагаясь на факт, что если у пользователя есть токен, он существует. (Поскольку дело не в том, существует ли пользователь)

Для любой другой логики, скажем, вы хотите проверить, разрешено ли ему публиковать или другие подобные ограничения, необходимо сделать вызов пользовательской службе.

Говоря о предоставлении доступа к базе данных, это будет противоречить одному из основных правил микросервисов. Это создаст тесную связь между вами и пользователем. В этом случае можно вызвать в службу пользователя, которая может решить, как обслужить этот запрос. Пользовательский сервис со своей стороны должен предоставлять способы ответа на ваши запросы в рамках SLA с помощью кэширования или других механизмов.

Еще одна вещь, которую вы можете изучить, - это Лучшая подруга (Backend для Frontend). Вы правильно сказали, что не должны открывать серверные службы для внешнего интерфейса или добавлять туда какую-либо логику, но часто интерфейсным страницам может быть неудобно принимать, что контент на той же странице отвечает через n разных серверных служб, и может быть некоторая логика для сшивания таких запросов и вот где вы можете использовать BFF. Бэкэнд-сервер (в моем случае node), который берет на себя такие вещи, как эти, требующие, чтобы интерфейс выполнял только один вызов (или меньше вызовов) для данной страницы и в то же время скрывает ваши внутренние службы внутри.

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