我已经阅读了很多有关它的主题,但是仍然没有找到更好的方法。
我有一个User
。一个User
可能有多个Posts
。用户和帖子是不同微服务。我正在使用Spring Boot。
当前端调用我的Posts
微服务向POST
发送/posts/user/1
请求时,我需要检查给定的userId
(1)是否在我的{ {1}}数据库。如果否,则抛出异常,告知前端用户不存在。如果是,则将给定的请求正文作为Users
插入。
问题是:我应该如何在后端检查此信息?我们不想让前端承担此责任,因为javascript是客户端的,恶意用户可以绕过此检查。
选项:
我知道它们之间的通信会产生耦合,但是我不确定让Posts访问Users数据库是否是最佳选择。
随时建议任何选项。
答案 0 :(得分:3)
您可以选择通过Post
方法在User
和RESTful
微服务之间进行进程间通信。
如果您只想检查资源的存在并且不希望任何主体作为响应,则应该使用HEAD
http方法。因此,托管在User
微服务上的API端点看起来像-
HEAD user/{userId}
从Post
微服务调用此API。
返回200 /如果用户存在,则确定
返回404 /如果用户不存在,则找不到
Click here和here,以获得有关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
是代表用户数据库的接口,而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()
方法,该方法将返回BAD REQUEST HTTP状态代码。