Spring Boot WebFlux Reactive MongoDB:如何在每个请求上切换数据库?

问题描述 投票:0回答:1

我正在使用Spring WebFlux和Reactive MongoDB进行SaaS项目。它必须是一个MultiTenant应用程序,每个租户都必须使用自己的数据库。

到目前为止,我刚刚将Reactive MongoDB依赖项添加到pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

然后我扩展了AbstractReactiveMongoConfiguration,以提供MongoClient和DatabaseName:

import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration;

@Configuration
public class DatabaseConfiguration extends AbstractReactiveMongoConfiguration {
    @Override
    public MongoClient reactiveMongoClient() {
        System.out.println("ReactiveMongoClient");
        return MongoClients.create();
    }

    @Override
    protected String getDatabaseName() {
        System.out.println("DataBase name");
        return "gateway";
    }
}

整个应用程序是OAuth 2.0资源服务器,我能够从ReactiveSecurityContextHolder中的Authentication中检索TenantID

public Mono<String> tenantID() {
    return ReactiveSecurityContextHolder.getContext()
            .switchIfEmpty(Mono.empty())
            .flatMap((securityContext) -> {
                Authentication authentication = securityContext.getAuthentication();

                if (authentication instanceof CustomAuthenticationToken) {
                    CustomAuthenticationToken customAuthenticationToken = (customAuthenticationToken) authentication;
                    Jwt jwt = customAuthenticationToken.getToken();

                    String issuer = jwt.getIssuer().toString();
                    return Mono.justOrEmpty(issuer);
                }

                return Mono.empty();
            });
}

为了根据执行请求的用户(身份验证)切换数据库的下一步是什么?

UPDATE:

This几乎接近目标,但差不多一年前@mp911de说不可能。想知道现在是否可行。如何在返回MongoDatabase之前实现返回Mono的真正的反应式ReactiveMongoDatabaseFactory,以便我可以访问SecurityContext,从而进行身份验证?

spring-data-mongodb spring-webflux multi-tenant
1个回答
0
投票

几个月前我遇到了同样的问题,想分享我的解决方法。

解决方案1: 自己动手

Spring没有为这个问题提供任何现成的解决方案。几个月前,我创建了一个解决方案的概念证明,并在Github上发布了示例项目。

spring-mongodb-multi-tenancy-example

简而言之:我创建了一个自定义MultiTenancyReactiveMongoTemplate,它基于subscriberContext中的tenantId在内部委托给实际的ReactiveMongoTemplatetenantId是从自定义WebFilter中的http-request标头中提取的,并将其放在subscriberContext中。

此解决方法在大多数情况下都有效,并且还支持自动索引创建和ReactiveMongoRepository的使用。

但是也有一些限制,因为MultiTenancyReactiveMongoTemplateReactiveGridFSTemplate上的事务,IndexOps不适用于所提供的解决方案。有些事情可以用其他委派的“模板”来实现,但是有些事情将永远无法工作,因为这些操作仅返回标量值(无Publisher),在这些情况下无法访问subscriberContext。

如果您不需要这些功能,则可以使用此解决方案。

解决方案2:

您为每个租户/客户启动和配置服务实例,并在这些服务之前放置一个反向代理。反向代理决定应使用哪个服务来处理请求。反向代理可以非常容易地实现,例如使用Spring Cloud Gateway,它使您可以轻松实现predicates,从而决定(例如,基于身份验证令牌)应使用的服务。

[借助CloudFoundry或Kubernetes之类的技术,不再难于协调这些特定于租户的服务的部署,并且该解决方案还使得轻松进行特定于租户的监视,警报甚至计费。

我们选择了解决方案2,因为总的来说这更容易,并且可以更好地扩展。

© www.soinside.com 2019 - 2024. All rights reserved.