跨不同微服务的数据验证

时间:2018-09-12 15:32:41

标签: java rest spring-boot architecture microservices

我已经阅读了很多有关它的主题,但是仍然没有找到更好的方法。

我有一个User。一个User可能有多个Posts。用户和帖子是不同微服务。我正在使用Spring Boot。

当前端调用我的Posts微服务向POST发送/posts/user/1请求时,我需要检查给定的userId(1)是否在我的{ {1}}数据库。如果否,则抛出异常,告知前端用户不存在。如果是,则将给定的请求正文作为Users插入。

问题是:我应该如何在后端检查此信息?我们不想让前端承担此责任,因为javascript是客户端的,恶意用户可以绕过此检查。

选项:

    微服务之间的
  • REST通信。 (发布微服务呼叫用户微服务,询问给定的ID是否在他身边)
  • Give将微服务访问权限发布到用户微服务的数据库

我知道它们之间的通信会产生耦合,但是我不确定让Posts访问Users数据库是否是最佳选择。

随时建议任何选项。

3 个答案:

答案 0 :(得分:3)

您可以选择通过Post方法在UserRESTful微服务之间进行进程间通信。

如果您只想检查资源的存在并且不希望任何主体作为响应,则应该使用HEAD http方法。因此,托管在User微服务上的API端点看起来像-

HEAD  user/{userId}

Post微服务调用此API。

  

返回200 /如果用户存在,则确定

     

返回404 /如果用户不存在,则找不到

Click herehere,以获得有关HEAD方法使用和用例的更多详细信息。

答案 1 :(得分:1)

对于这个非常特殊的用例,如果您具有安全层,则可以(应该)使用用户访问令牌,以确保为正确的用户处理了请求,这可以通过验证令牌和依靠以下事实:如果用户具有令牌,则该令牌存在。 (因为这与用户是否存在无关)

对于除此以外的任何逻辑,例如,您要检查是否允许他发帖或进行其他此类限制,以便致电用户服务。

谈论授予数据库访问权限,这将违反微服务的一项基本准则。这样做会在您和用户之间形成紧密的联系。在这种情况下,可以致电用户服务,这可以决定如何处理此请求。 用户服务本身应该提供通过缓存或其他机制在SLA中回答您的查询的方法。

您可以探索的另一件事是BFF(前端后端) 您正确地说,您不应该将后端服务公开给前端或在其中添加任何逻辑,但是前端页面通常可能无法接受通过n个不同的后端服务来回答同一页面上的内容,并且可能会有一些逻辑来缝合此类查询那就是您可以使用BFF的地方。 后端服务器(在我的案例中为节点)需要类似这样的事情,即要求前端仅对给定页面进行一次调用(或更少的调用),同时将您的后端服务隐藏在其中。

答案 2 :(得分:-1)

是的,您必须在后端进行验证,因为我想这是一种REST服务,并且请求不仅可以从UI发送。

假设您有一个服务实现:

@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是代表用户数据库的接口,而UserNonExistentRuntimeException。然后,您可以在控制器中执行以下操作:

@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()方法,该方法将返回BAD REQUEST HTTP状态代码。