使用 Spring Security 保护 REST 微服务

Posted

技术标签:

【中文标题】使用 Spring Security 保护 REST 微服务【英文标题】:Securing REST microservices with Spring Security 【发布时间】:2017-05-27 21:02:32 【问题描述】:

我正在寻找一种最佳实践和高效的解决方案来保护通过 REST 与 Web 客户端应用程序进行通信的多个微服务。

当前设置

这些微服务是用 Java 制作的,带有 Spring 框架并运行到 Docker 容器中。

客户端是一个 Angular 2 应用程序。

我创建了一个新的 µService,它将充当“网关”并且是我的 Web 客户端和我的其他服务之间的唯一通信点。

我从远程身份验证 API 检索 JWT 加密令牌(我们称之为 LOCK)

我正在考虑的解决方案

我可以将登录 JWT 存储到一个 cookie 中,然后发送到网关。

网关将令牌嵌入到发送给相关 µService 的最终有效负载中,如果用户是新用户,则将其存储到数据库中。

然后微服务获取查询,在远程身份验证服务中检查用户角色,如果足够,则返回 200 状态和结果。

编辑

我们需要在我们的 µServices 配置单元中加入一个 RabbitMQ 代理,这样才能使用 WebSocket。为了以与保护 REST API 相同的方式保护 WebSockets,我不确定我们是否仍然应该在网关中管理安全性,并且可能在微服务级别自行管理它。因为很多消息会传输,我们也许应该去掉一个会减慢传输速度的中间件。

问题

这是一个好习惯吗?有什么可以做得更好?您是否有任何满足相同需求的示例?非常感谢您的分享和想法。

【问题讨论】:

我采用了类似的方法,但在一个方面有所不同。用户 JWT 令牌不会从网关向下传递给服务。网关本身获取客户端令牌并使用它向其他服务验证自己。我选择这种设计的原因是为了让用户的安全性本地化在网关中。并且网关完全被其他服务信任。 是的,我告诉自己同样的事情。此外,无论如何都必须存储 JWT 令牌,因此最好将其放置在单个入口点中以避免数据复制(如果需要,网关仍然可以进行水平可扩展性)。为了防止 cookie/会话信息被盗,我可以将数据库版本与存储在 Web 浏览器中的版本进行比较。恼人的效果是,µService 会在彼此之间产生大量 HTTP 流量,而这似乎不是组织这些流量的“好”方式。 在我看来,身份验证服务器应该是微服务之一,它可以对授权和身份验证做任何事情。例如管理和存储令牌到数据库,检查用户的权限。其他微服务需要自行检查token是否有效,如果token过期会返回错误码给客户端,客户端会再次调用refresh token。为检查用户的权限,每个微服务都可以调用认证服务器来检查权限。 你可以从这个文档中得到一些想法livebook.manning.com/book/microservices-in-net-core/chapter-10/… 或许也可以看看 istio (istio.io/latest/docs/concepts/security) 【参考方案1】:

我会这样做:

考虑到每个微服务都在 apigateway 后面,甚至是身份验证/授权微服务 -> 让我们简称为 auth

一旦请求到来,apigateway 会与 auth 服务进行检查,auth 服务会执行所需的操作以验证令牌和请求者是否合法,并以 200/401(/403) 回复 apigateway。

如果 apigw 得到 200,它将请求转发到该端点上的任何微服务,否则返回其他状态。

如果我们考虑这种情况,并且认为它是通过 apigateway 进入您的环境的唯一入口点,我认为您没有任何理由保护其他服务之间的通信。

让我们考虑一下这种情况:

client -> calls POST /api/v1/cars

    在客户端和 apigw 之间我们有一个安全的调用,因为显然我们将使用证书......因此客户端将调用 https://..../api/v1/cars 请求到达apigw,它解密请求 得到jtw asks auth -> 这个返回 200 将请求转发给CarsMicroservice Cars 微服务信任该请求,因为它知道其他人已经对 JTW 签名进行了解密,因此可以安全地假设其中的任何信息都是合法的 如果 carsMicroservice 需要一些特定于用户的信息,例如这是用于创建新车的帖子,出于某种原因,我们需要一个用户名,而不是使用 JWT 令牌中的 subject 字段,即用户的 uuid -> 汽车关联,所以当请求到达 carsMicroservice 时,它​​将DECODE 有效载荷,获取用户 uid,要求 userMicroservice 返回有关具有该 uid 的用户的所有信息。这种通信不需要安全,因为它是在所有必要的安全检查之后在内部完成的。

当然,您可以强制用户只能访问他自己的用户信息等,但这些都是自定义启发式的。

【讨论】:

【参考方案2】:

此外,您可能必须在微服务之间建立信任。您可以使用以下组合:

使用 LDAP/OAuth2 令牌 使用 IP 白名单 CORS 规则 https

【讨论】:

以上是关于使用 Spring Security 保护 REST 微服务的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Security 保护 REST API

使用 spring-security-oauth2 2.0.5.RELEASE 保护 Spring REST 服务

如何使用 Spring Security 和 Angularjs 保护 Spring Rest 服务?

使用 Spring Security Rest 插件保护 Grails Rest Api

Spring starter security or spring cloud security 如何保护整个微服务架构?

使用 Spring Security 保护 REST 微服务