如何使用Key斗篷和Spring Boot OAuth2客户端实现单点登录(SSO)多租户功能



问题

在Spring Boot中为多个OAuth2提供程序实现SSO登录。

设置

两个Spring Boot web应用程序(App1和App2(,它们被配置为OAuth2客户端。两者都将与具有两个领域的Key斗篷授权服务器进行通信。

业务要求

  • 实现单一登录功能(SSO(
  • 具有共享用户群的多租户
  • 任何时候只有一个用户可以访问一个租户

我有两个spring-boot应用程序,它们是在docker容器中运行的OAuth2客户端。我们正在为每个租户设置多个Key斗篷领域。从Spring的角度来看,我们包含了两个提供程序的自动配置属性,其中每个提供程序都将映射到不同的Keycloft领域。因此,属性将如下所示:

  • spring.security.oauth2.client.provider.realm1
  • spring.security.oauth2.client.provider.realm2

行为

当用户登录到第一个应用程序(App1(时,Spring会显示一个生成的html页面。此页面显示从application.properties配置的每个提供程序的列表,作为登录的选项。

用户可以选择一个,然后重定向到Key斗篷登录页面,该页面具有从Spring的提供程序属性映射的领域。然后,当成功登录时,用户会按预期重定向回。

我们使用Spring Mongo会话来存储会话信息,并且我们还在Key斗篷管理客户端中看到了显示活动会话的领域。

当试图访问另一个应用程序(App2(时,Spring不会检测到用户或会话,并将显示相同的生成html页面,该页面显示要选择和登录的提供者。

当点击同一个提供者(领域(时,Spring会找到会话,并被重定向到请求的资源,一切都很好。这部分是我尝试在不首先询问提供者的情况下实现的。主要原因是为了强制执行业务要求,即会话中的用户一次不能访问多个领域。

尝试的解决方案

提供一个Spring Security登录控制器,该控制器将有一个服务层来查找mongo会话,然后构建Spring在单击列表中的提供程序时生成的OAuth2链接。

但是,我还没有用户。当打开另一个选项卡时,这也会成为一个问题,因为我认为我对从第一个应用程序创建的cookie没有任何作用域。

我唯一能想到的另一件事是尝试获取客户端ip并将其存储在会话中,以便稍后可以找到它。然而,当使用nginx代理配置时,这就成了一个问题,因为我似乎无法获得实际的ip,而且似乎总是获得代理ip,即使使用了我从文档中看到的nginx头。

问题

是否可以找到会话并以编程方式重定向到请求的提供程序?

注意:我目前知道可用的密钥斗篷启动器依赖项,但我试图看看是否有一个更面向Spring的解决方案,其通用OAuth2客户端安全配置。

前端解决方案

  1. 用户导航到app1,app1未检测到用户会话(需要登录(,app1将用户重定向到app2,并使用一些指示重定向目的的查询参数
  2. App2接收重定向请求并检查会话是否存在(用户登录到App2(。现在你可以处理它了。重定向回app1或显示一些错误,等等
  3. 用户未登录到app2,app2重定向回app1,并指示";节目提供者">

对称行为也应在app1上实现。

根据安全要求,可以对查询参数进行加密,以防止手动url黑客攻击。

如果您需要进一步的保护,可以扩展Key斗篷身份验证功能,以检查会话存储中是否有已登录的用户。

最新更新