如何在新的 Spring Authorization 服务器中实现多租户
授权服务器链接: https://github.com/spring-projects/spring-authorization-服务器
这个项目几乎包含了 OAuth 和身份提供者方面的所有内容。 我的问题是,如何在身份提供商级别实现多租户。
我知道一般来说有多种方法可以实现多租户。
我感兴趣的场景是这样的:
- 一个组织为多个租户提供服务。
- 每个租户都与一个单独的数据库关联(包括用户数据的数据隔离)
- 当用户访问
专用前端应用程序(每个租户)
并协商来自身份提供商
的访问令牌 - < code>身份提供商然后识别租户(基于标头/域名)并使用
tenant_id
生成访问令牌
, - 然后此
访问令牌
被传递到下游服务,其中可以提取tenant_id
并决定数据源
我对上述所有步骤都有一个大概的了解,但我不确定第4点。
我不确定如何为不同的租户配置不同的数据源身份提供者?如何在Token中添加tenant_id?
问题链接: https://github.com/ spring-projects/spring-authorization-server/issues/663#issue-1182431313
Link for Authorization server: https://github.com/spring-projects/spring-authorization-server
This project pretty much has everything in terms of OAuth and Identity provider.
My question is, How to achieve multi-tenancy at the Identity provider
level.
I know there are multiple ways to achieve multi-tenancy in general.
The scenario I am interested in is this:
- An organization provides services to multiple tenants.
- Each tenant is associated with a separate database (Data isolation including user data)
- When a user visits
dedicated Front-end app(per tenant)
and negotiate access tokens fromIdentity provider
Identity provider
then identifies tenant (Based on header/ Domain name) and generatesaccess token
withtenant_id
- This
access token
then is passed on to down-stream services, which intern can extracttenant_id
and decide the data source
I have a general idea about all the above steps, but I am not sure about point 4.
I am not sure How to configure different data sources for different tenants on the Identity Provider? How to add tenant_id in Token?
Link to the issue: https://github.com/spring-projects/spring-authorization-server/issues/663#issue-1182431313
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这确实是一个很好的问题,我真的很想知道如何在新的授权服务器中以正确的方式做到这一点。在 Spring Resource Server 中有一个关于多租户的部分。我成功了。
至于新的 Spring 授权服务器多租户问题。我还对密码和客户端凭据授予类型执行了此操作。
但请注意,虽然它可以工作,但这是多么完美。我不知道,因为我只是为了学习而这样做。这只是一个样本。当我为授权代码授予类型执行此操作时,我也会将其发布到我的 github 上。
我假设主数据库和租户数据库配置已完成。我无法在这里提供完整的代码,因为它有很多代码。我只会提供相关的片段。但这只是
我使用单独数据库的示例。我所做的我在 AuthorizationServerConfiguration 中使用了类似以下内容的内容。
这是我的 TenantFilter 代码
这是 TenantDBContextHolder 类
现在已经有主数据库和租户数据库的配置。在这些配置中,我们还检查 TenantDBContextHolder
类是否包含该值。因为当请求令牌时,我们会检查请求并将其设置在 TenantDBContextHolder 中。因此,基于该线程局部变量连接正确的数据库并将令牌发布到正确的数据库。然后在令牌定制器中。您可以使用类似以下内容
现在我假设资源服务器也配置为多租户。这是链接 Spring Security 资源服务器多租户< /a>.基本上,您必须为多租户配置两个 bean,如下所示
现在为 spring 配置两个类。您可以从中获取令牌中的租户标识符。
同样
,现在授权码授予类型授权类型流程又如何呢?在这种情况下我也得到了租户标识符。但是,当它将我重定向到登录页面时,我丢失了租户标识符,因为我认为它根据授权代码请求创建了登录页面的新请求。无论如何,我不确定它,因为我必须研究授权代码流的代码它实际上在做什么。因此,当它将我重定向到登录页面时,我的租户标识符正在丢失。
但是,在密码授予类型和客户端凭据授予类型的情况下,没有重定向,因此我得到在后续阶段中,租户标识符我可以成功地使用它来放入我的令牌声明中。
然后在资源服务器上我获取发行者 url。从颁发者 URL 获取租户标识符。验证一下。它连接到资源服务器上的租户数据库。
我是如何测试的。我用的是spring客户端。您可以自定义授权码请求流程。包含自定义参数的密码和客户端凭据。
谢谢。
------------------ 解决多租户的授权码登录问题 -------------
我解决了这个问题也。实际上我在安全配置中做了什么。我使用了以下配置
实际上,问题是在授权代码的情况下,您首先重定向到登录页面。成功登录后,您会看到同意页面。但是当您进入同意页面时,您就丢失了租户参数。
原因是spring内部类OAuth2AuthorizationEndpointFilter拦截了Authorization Code的请求。它检查用户是否经过身份验证。如果用户未经过身份验证,则会显示登录页面。成功登录后,它会检查是否需要同意。如果需要,它会创建一个仅包含三个参数的重定向 uri。这是spring内部代码
看到上面的方法是私有的,我发现没有办法可以自定义它。可能有,但我没找到。无论如何,现在您的同意控制器已被调用。但没有租户标识符。你无法得到它。并且在同意后,它无法以标识符连接到租户数据库。
因此,第一步是将租户标识符添加到登录页面。登录后,您应该拥有此租户标识符,以便您可以在同意页面上进行设置。之后,当您提交同意书时,该参数就会出现。
顺便说一句,我前段时间做过,可能我错过了一些东西,但这就是我所做的。
现在如何在登录页面获取参数。我使用以下方法解决了它。首先,我创建了一个常量,因为我必须多次访问该名称
创建以下类
然后在我的登录控制器上使用以下代码获取它
所以这是我在发送的登录页面中拥有租户标识符的第一步按要求给我。
现在是我在安全配置中使用的配置。您可以看到我正在使用 TenantUsernamePasswordAuthenticationFilter。这是文件管理器
,在配置中,我在此过滤器上设置 TenantWebAuthenticationDetailsSource,这里是
类
。现在,在 spring 对用户进行身份验证后,我将详细了解租户名称。然后在我使用的同意控制器中
,现在我的同意页面上有我的租户标识符。提交后,它位于请求参数中。
我使用了另一个类,无论如何
,这就是我解决它的方法。我的任何项目中都没有任何此类要求,但我想使用这个新服务器来完成它,所以我只是用这种方式解决了它。
无论如何,有很多代码。我使用 Spring oauth2 客户端对其进行了测试,并且它可以正常工作。希望我能创建一些项目并将其上传到我的 Github 上。一旦我再次运行它,我将在这里对流程进行更多解释。特别是最后一部分,提交同意后如何在线程局部变量中设置。
之后一切就变得简单了。
希望它会有所帮助。
谢谢
This is really a good question and I really want to know how to do it in new Authorization Server in a proper way. In Spring Resource Server there is a section about Multitenancy. I did it successfully.
As far as new Spring Authorization Server multitenancy concerns. I have also done it for the password and the Client Credentials grant type.
But please note that although it is working but how perfect is this. I don't know because I just did it for learning purpose. It's just a sample. I will also post it on my github when I would do it for the authorization code grant type.
I am assuming that the master and tenant database configuration has been done. I can not provide the whole code here because it's lot of code. I will just provide the relevant snippets. But here is just the sample
I used the separate database. What I did I used something like the following in the AuthorizationServerConfiguration.
Here is my TenantFilter code
Here is the TenantDBContextHolder class
Now as there is already configuration for master and tenant database. In these configurations we also check for the TenantDBContextHolder
class that it contains the value or not. Because when request comes for token then we check the request and set it in TenantDBContextHolder. So base on this thread local variable right database is connected and the token issue to the right database. Then in the token customizer. You can use something like the following
Now I am assuming that the Resource Server is also configure for multitenancy. Here is the link Spring Security Resource Server Multitenancy. Basically You have to configure two beans for multitenancy like the following
Now two classes for spring. From which you can get the tenant Identifier from your token.
Similarly
Now what about authorization code grant type grant type flow. I get the tenant identifier in this case too. But when it redirects me to login page then I lost the tenant identifier because I think it creates a new request for the login page from the authorization code request. Anyways I am not sure about it because I have to look into the code of authorization code flow that what it is actually doing. So my tenant identifier is losing when it redirects me to login page.
But in case of password grant type and client credentials grant type there is no redirection so I get the tenant identifier in later stages and I can successfully use it to put into my token claims.
Then on the resource server I get the issuer url. Get the tenant identifier from the issuer url. Verify it. And it connects to the tenant database on resource server.
How I tested it. I used the spring client. You can customize the request for authorization code flow. Password and client credentials to include the custom parameters.
Thanks.
------------------ Solve the Authorization Code login problem for multitenancy -------------
I solved this issue too. Actually what I did in my security configuration. I used the following configuration
Actually the problem was in case of Authorization Code is that you first redirect to login page. After successfully login you see the consent page. But when you comes to consent page then you lost the tenant parameter.
The reason is the spring internal class OAuth2AuthorizationEndpointFilter intercepts the request for Authorization Code. It checks user is authenticated or not. If user is not authenticated then it shows the login page. After successfully login it checks if consent is required. And if required then it makes a redirect uri with just three parameters. Here is the spring internal code
See the above method is private and I found no way that I can customize it. May be there is but I didn't find it. Anyways now your consent controller is call. But there is no tenant Identifier. You can't get it. And after consent there is no way that it connects to tenant database base in identifier.
So the first step is to add tenant identifier to login page. And then after login you should have this tenant identifier so you can set it on your consent page. And after that when you submit your consent form then this parameter will be there.
Btw I did it some time ago and may be I miss something but this is what I did.
Now how you get your parameter at login page. I solved it using the following. First I created a constant as I have to access the name from multiple times
Create the following class
Then on my Login controller I get it using the following code
So this is the first step that I have my tenant identifier in my login page that is send to me by request.
Now the configuration that I used in my Security configuration. You can see that I am using TenantUsernamePasswordAuthenticationFilter. Here is the filer
And in the configuration I am setting TenantWebAuthenticationDetailsSource on this filter which is here
Here is the class
Now after spring authenticates the user then I have the tenant name in details. Then in the consent controller I use
Now I have my tenant identifier on my consent page. After submitting it it's in the request parameter.
There is another class that I used and it was
Anyways this is how I solved it. I don't have any such requirement in any of my project but I want to do it using this new server so I just solved it in this way.
Anyways there is lot of code. I tested it using the Spring oauth2 client and it was working. Hopefully I will create some project and upload it on my Github. Once I will run it again then I will put more explanation here of the flow. Specially for the last part that after submitting the consent how it set in the Thread Local variable.
After that everything is straight forward.
Hopefully it will help.
Thanks
这与 Spring auth Server 无关,但与我们可以考虑的方法相关 #
4
我记得上次我们实现了类似的方法,我们有以下选项
更多详细信息可以从此处阅读
This is not related to Spring auth Server, but related to approaches that we can think for point #
4
I remember the last time we implemented a similar approach, where we had below options
More details can be read from here
很高兴分享,这最终通过 https://github 实现.com/spring-projects/spring-authorization-server/issues/663
尚未测试。不要忘记贡献
So happy to share , this has been finally implemented via https://github.com/spring-projects/spring-authorization-server/issues/663
Yet to test it out. Don’t forget to contribute