具有 api 网关的微服务授权模式
Microservice authorization pattern with api gateway
假设我正在开发博客平台,用户可以在其中注册帐户、支付订阅费用并创建自己的博客。平台由以下微服务组成:
- 账户服务
- 授权服务
- 订阅服务
- 博客服务
- api-网关
我正在考虑实施 api-gw 模式,其中除 api-gw 之外的所有微服务都将部署到私有网络(在那里它们可以同步或直接相互对话)通过消息代理异步)并且它们将仅通过 api-gw.
公开可用
会有两个clients/consumers的API:
- 前端(面向客户)
- cms(对于管理员)
因此我想使用 separate-api-gw-per-client 模式,所以实际上会有两个 api 网关,一个用于常规前端(frontent-api-gw) 和一个用于 cms (cms-api-gw),但两者都将与相同的微服务对话。
我的问题是关于授权以及它应该在哪里进行(或者更确切地说,pros/cons 对于不同的方法是什么)。让我们关注两个 "endpoints":
- 前端-api-gw::createBlog() => 博客服务::createBlog()
前端 api-gw 公开端点以创建新博客,此 api 调用是 "forwarded" 到 blog-service::createBlog() 端点。假设用户已经通过身份验证(即带有用户 ID 的正确 JWT 与请求一起传递给 api-gw)。
必须进行的授权是确定具有此id的用户是否可以创建新博客。这可以通过调用订阅服务来检查用户是否已付费订阅来完成。主要问题是此授权是否仍应在 api-gw 端 (A) 或博客服务端 (B) 进行:
- cms-api-gw / frontend-api-gw::listBlogs() => 博客服务::listBlogs()
类似情况 - 是否应将任何格式的 userContext / JWT 传递给每个单独的微服务,并且该微服务应决定传递什么 return?或者个别微服务不应该知道 userContext(可能仅用于日志记录目的),依赖 API GW 授权并且只接收一些 parameters/arguments?
我的想法:
在案例 A 中,由于授权层的原因,每个单独的微服务中的逻辑更加复杂。可以变得更复杂,那里会有更多 API gws、用户角色等。
然而 API GW 在这种情况下更简单,它只将请求转发给微服务。
在案例 B 中,每个单独的微服务中的逻辑都不那么复杂、简单和直接。然而在API GW 中有更多的逻辑,因为它必须实现对所有平台的授权(至少对于这个api gw 负责的部分)。也许将所有授权集中在一个地方而不是分散在微服务中也可能是一个优势?
另外,在情况 B 中,我认为各个微服务之间的耦合较少。
你们怎么看待这两种方法/也许你们还有其他方法"ideas"?
根据我的经验,我发现情况 A 最容易 scale/maintain。授权逻辑可能会与业务逻辑混淆。
例如,假设您要授权 /updateBlog?id=52143 方法。在网关中这样做必须知道该用户不仅获得授权,而且他们拥有该特定博客,或者他们有权更新委托给他们的博客。
将所有这些逻辑导出到您的网关是可能的,但很棘手,并且最终感觉高度重复。当逻辑发生变化并在系统中级联时,这会变得更加痛苦。例如,假设您的 /updateBlog 授权现在有 "guest updaters"。必须对您的 /updateBlog 服务和您的网关进行同步更新比较棘手,而且成本更高。
故事的寓意是,在边界验证,在服务中授权。
假设我正在开发博客平台,用户可以在其中注册帐户、支付订阅费用并创建自己的博客。平台由以下微服务组成:
- 账户服务
- 授权服务
- 订阅服务
- 博客服务
- api-网关
我正在考虑实施 api-gw 模式,其中除 api-gw 之外的所有微服务都将部署到私有网络(在那里它们可以同步或直接相互对话)通过消息代理异步)并且它们将仅通过 api-gw.
公开可用会有两个clients/consumers的API:
- 前端(面向客户)
- cms(对于管理员)
因此我想使用 separate-api-gw-per-client 模式,所以实际上会有两个 api 网关,一个用于常规前端(frontent-api-gw) 和一个用于 cms (cms-api-gw),但两者都将与相同的微服务对话。
我的问题是关于授权以及它应该在哪里进行(或者更确切地说,pros/cons 对于不同的方法是什么)。让我们关注两个 "endpoints":
- 前端-api-gw::createBlog() => 博客服务::createBlog()
前端 api-gw 公开端点以创建新博客,此 api 调用是 "forwarded" 到 blog-service::createBlog() 端点。假设用户已经通过身份验证(即带有用户 ID 的正确 JWT 与请求一起传递给 api-gw)。
必须进行的授权是确定具有此id的用户是否可以创建新博客。这可以通过调用订阅服务来检查用户是否已付费订阅来完成。主要问题是此授权是否仍应在 api-gw 端 (A) 或博客服务端 (B) 进行:
- cms-api-gw / frontend-api-gw::listBlogs() => 博客服务::listBlogs()
类似情况 - 是否应将任何格式的 userContext / JWT 传递给每个单独的微服务,并且该微服务应决定传递什么 return?或者个别微服务不应该知道 userContext(可能仅用于日志记录目的),依赖 API GW 授权并且只接收一些 parameters/arguments?
我的想法:
在案例 A 中,由于授权层的原因,每个单独的微服务中的逻辑更加复杂。可以变得更复杂,那里会有更多 API gws、用户角色等。 然而 API GW 在这种情况下更简单,它只将请求转发给微服务。
在案例 B 中,每个单独的微服务中的逻辑都不那么复杂、简单和直接。然而在API GW 中有更多的逻辑,因为它必须实现对所有平台的授权(至少对于这个api gw 负责的部分)。也许将所有授权集中在一个地方而不是分散在微服务中也可能是一个优势?
另外,在情况 B 中,我认为各个微服务之间的耦合较少。
你们怎么看待这两种方法/也许你们还有其他方法"ideas"?
根据我的经验,我发现情况 A 最容易 scale/maintain。授权逻辑可能会与业务逻辑混淆。
例如,假设您要授权 /updateBlog?id=52143 方法。在网关中这样做必须知道该用户不仅获得授权,而且他们拥有该特定博客,或者他们有权更新委托给他们的博客。
将所有这些逻辑导出到您的网关是可能的,但很棘手,并且最终感觉高度重复。当逻辑发生变化并在系统中级联时,这会变得更加痛苦。例如,假设您的 /updateBlog 授权现在有 "guest updaters"。必须对您的 /updateBlog 服务和您的网关进行同步更新比较棘手,而且成本更高。
故事的寓意是,在边界验证,在服务中授权。