我正在考虑在我的微服务之上使用 api 网关。但是有一些架构问题我没有明确的答案,所以我想从社区获得意见。如果你能分享你对好的和坏的做法的想法,那也很棒。因此,为了使这个问题帖子易于阅读,我有两个主要部分“问题”和“详细信息”
问题
Api网关应该负责授权和请求转换吗?
问题主要是,什么是网关:它只是 api 用户和微服务之间的桥梁。还是微服务的版主?请参阅“网关实施策略”部分了解更多信息。
在使用 Amazon API Gateway 的情况下,使用额外的 lambda 函数层对请求进行转换和授权是一种好习惯吗?
如果我选择使用 Amazon API Gateway,那么对上一个问题的回答将是“网关应该充当微服务的主持人”。比我需要通过 Amazon lambdas 处理请求/响应转换和授权,这意味着我将在网关下方有另一层。所以问题是:拥有这种架构是一种好习惯吗?
细节
技术
- 春季启动 2.0
- 智威汤逊
- Spring Cloud Gateway或Amazon Api Gateway(取决于答案)
服务
我们的系统中有以下微服务
服务A
端点 GET /api/resources/{dataId}/admin-endpoint
标头 - 授权:不记名令牌
此端点只能由具有 ADMIN 角色的用户访问(如果来自没有该角色的用户的请求,将返回 403 http 状态和响应)。
请注意,在处理请求之前,令牌必须由 AuthService 验证。并且在处理请求后(在非错误http状态的情况下)令牌必须由AuthService刷新(响应必须包含刷新的令牌)
端点 GET /api/resources/{dataId}/user-endpoint
标头 - 授权:不记名令牌
具有任何角色的用户都可以访问此端点
身份验证服务
端点 POST /api/auth/login
标头 - 授权:不记名令牌
正文 - {“用户名”:字符串,“密码”:字符串}
验证用户:在成功的情况下,签名的授权令牌将作为响应的标头(不记名 JWT 令牌)返回。如果认证失败,将返回 401 http 状态
端点 POST /api/auth/logout
标头 - 授权:不记名令牌
使授权令牌无效(通过将令牌存储在适当的表中),以便用户无法使用给定令牌访问受保护的 API
端点 GET /api/auth/validate
标头 - 授权:不记名令牌
验证给定令牌(必须在 ServiceA 中处理请求之前调用。有关验证检查,请参见附录 A
响应正文 - {“角色”:,“用户名”:字符串}
网关实施策略
网关只负责路由
使用此策略 ServiceA 和 AuthService 在网关中注册为路由,在处理请求之前无需进行额外的请求转换。
ServiceA 直接与 AuthServer 对话以进行授权和令牌验证。
优点
- 网关逻辑非常简单
- 作为网关,有多种框架和工具可供选择。
缺点
- ServiceA 和 AuthService 强耦合
- 如果我需要添加 ServiceB,那么我需要做一些双重工作来建立 ServiceB 和 ServiceA 之间的通信
- 处理 AuthService 中的失败主要由 ServiceA 完成
Gateway负责授权和请求转换
使用此策略,api-gateway 将在将请求传递给 ServiceA 之前使用 AuthServer 处理令牌验证。当 ServiceA 给出非错误响应时,它也会处理令牌刷新
优点
- ServiceA 与 AuthService 完全解耦
- 添加另一个 ServiceB 会容易得多
- AuthService 失败由网关处理
缺点
- 网关将承担更多的责任,而不仅仅是作为微服务的桥梁
- Amazon Api Gateway 很可能不是一个好的选择,因为使用 Amazon lambda-s 处理授权和转换可能非常痛苦(也许我错了)
附录 A:JWT 令牌验证检查
- 令牌具有有效的承载前缀:“承载”
- 令牌未过期(令牌有createdAt属性,用于判断令牌是否超过10分钟)
- 用户存在:创建token后用户没有被删除(token有subject属性,保持用户的唯一标识)
- 在令牌生命周期内未更改用户密码