spring-boot - 如何将用户的身份验证(和授权)传播到其他微服务
问题描述
我为登录页面创建了一个微服务(使用 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 security 将帮助您在服务“A”中对用户“Foo”进行身份验证/授权,但它与身份传播无关。
毕竟,服务“B”可以是根本不用spring或java编写的东西,甚至是一些外部系统。
这里有很多方法,具体取决于通常归结为的要求:
依靠只有登录页面(服务 A)是您通往外部世界的“网关”这一事实,因此此服务需要安全性
保护所有服务(例如在每个服务中放置 spring security 或任何其他安全组件)
与“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 将查询其他服务等等。
推荐阅读
- python - 用于点名的 Django 动态表单
- c# - 尝试上传文件并在视图中显示文件
- javascript - Current Date converted to 10 days before and 10 days after
- python - Google colab:在子进程中打印
- python - 带有带引号的可选值的 argparse “--options --for --other --cmd”
- django - Elasticsearch 文档字段类型索引自动更改
- html - text/html 404 notFound 当需要在角度中使用图像背景时
- r - 如何在 R 中将多维 data.frame 转换为一维 data.frame
- botframework - 电子邮件技能:Microsoft.Graph.ServiceException
- r - 创建分位数摘要时出错,平均值