如何将用户的身份验证(和授权)传播到其他微服务



我已经为登陆页面创建了一个微服务(使用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();
}

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

这里有很多问题。

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

毕竟,服务"B"可能根本不是用 spring 或 java 编写的,甚至是某个外部系统。

根据需求,这里有许多方法,通常归结为:

  1. 依靠这样一个事实,即只有登陆页面(服务 A(是您通往外部世界的"门户",因此此服务需要安全性

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

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

这里的另一个问题是,从服务 A 调用服务 B 的"行为"到底意味着什么。

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

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

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

因此,当您在 RestTemplate 中构造请求(反过来依赖于 okHttp、Apache Http 客户端或其他任何(时,底线将具有额外的标头来提供身份信息(再次由您决定这里的"身份"到底是什么(。

反过来,服务"B"应该在某种过滤器中再次解析这个对象(理想情况下,如果"B"也在弹簧中,则在它命中其余控制器之前(,或者如果你在服务B上安装了它,甚至使用弹簧安全性,并根据该身份做出"保护决策",然后再次,如果B将查询其他服务,则再次将其放在本地线程上,依此类推。

您可以尝试使用WebSecurityConfigurerAdapter并覆盖 BeanAuthenticationManagerBuilder配置,这将允许您设置角色。

这篇文章有一个很好的例子:https://www.journaldev.com/8748/spring-security-role-based-access-authorization-example

最新更新