问题
在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客户端安全配置。
前端解决方案
- 用户导航到app1,app1未检测到用户会话(需要登录(,app1将用户重定向到app2,并使用一些指示重定向目的的查询参数
- App2接收重定向请求并检查会话是否存在(用户登录到App2(。现在你可以处理它了。重定向回app1或显示一些错误,等等
- 用户未登录到app2,app2重定向回app1,并指示";节目提供者">
对称行为也应在app1上实现。
根据安全要求,可以对查询参数进行加密,以防止手动url黑客攻击。
如果您需要进一步的保护,可以扩展Key斗篷身份验证功能,以检查会话存储中是否有已登录的用户。