使用 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 如何保护整个微服务架构?