首页 > 解决方案 > 如何将用户的身份验证(和授权)传播到其他微服务

问题描述

我为登录页面创建了一个微服务(使用 Spring boot)。用户提供凭据,成功登录后,他可以看到仪表板。我使用RestTemplate从仪表板遍历到其他微服务。以下是代码片段:

    @Autowired
private RestTemplate restTemplate;

@GetMapping("/employeeCenter")
public String openEmployeeCenterApp() {
    logger.info("Invoking EmployeeCenter micro-service");
    return restTemplate.getForEntity("http://EMPLOYEE-SERVICE/empCenter/", String.class).getBody();
}

哪个工作正常。但我想将用户的身份验证(和授权)传播到任何其他微服务;这样基于用户的特权,我可以显示/隐藏东西。这样做的合适方法是什么?

标签: spring-bootspring-securitymicroservices

解决方案


这里有很多担忧。

当“登陆页面”服务(我们称其为“A”)显示具有身份“Foo”的用户的仪表板并尝试通过 Rest 模板联系另一个服务“B”(这是另一个进程)时,您应该实现身份传播“Foo”,它不是春季安全的工作。Spring security 将帮助您在服务“A”中对用户“Foo”进行身份验证/授权,但它与身份传播无关。

毕竟,服务“B”可以是根本不用spring或java编写的东西,甚至是一些外部系统。

这里有很多方法,具体取决于通常归结为的要求:

  1. 依靠只有登录页面(服务 A)是您通往外部世界的“网关”这一事实,因此此服务需要安全性

  2. 保护所有服务(例如在每个服务中放置 spring security 或任何其他安全组件)

  3. 与“1”类似,但区分安全网关和登录页面 - 有两个微服务,因此网关将受到保护,并向最终用户“开放”,同时也向内部通信开放。不同之处在于,如果您需要从服务“A”调用服务“B”,您可以通过网关进行,它会检查安全性

这里的另一个问题是从服务 A 调用服务 B 的“行为”究竟是什么意思。

  • 一件事是告诉“我是用户 Foo(目前在服务 A 中),我将 B 称为 Foo。
  • 另一件事是告诉“我是服务 A(有自己的身份),我代表用户 Foo 调用服务 B”。

所有这些问题都属于安全相关架构领域,可以采用许多解决方案。如果您必须进行这样的分析(尽管它超出了这个问题的范围),请确保您了解每种方法的性能影响: - HTTP 跃点可能很昂贵 - 数据库跃点(以防您不得不求助于数据库)很昂贵 尽可能应用缓存

现在,从技术上讲,您应该提供一些过滤器,如果您运行反应式堆栈,它将添加从线程本地或类似解决方案中获取的身份标头。因此,在最简单的情况下,您可以将身份对象放在某个本地线程上,然后在过滤器中获取它以添加请求。

因此,当您在 RestTemplate 中构建请求时(该请求又依赖于 okHttp、Apache Http 客户端或其他),它将具有额外的标头来提供身份信息(再次由您决定究竟什么是“身份”在这里)。

反过来,服务“B”应该在某种过滤器中再次解析这个对象(如果“B”也在spring中,最好在它到达rest控制器之前),或者如果你将它安装在服务B上,甚至使用spring security,并且根据该身份做出其“保护决策”,然后再次将其放在线程本地,如果 B 将查询其他服务等等。


推荐阅读