使用Spring安全JPA的多租户

时间:2012-03-15 13:14:18

标签: spring-security multi-tenant

这是对此Multitenancy with Spring JPA

的跟进

我选择使用'AbstractRoutingDataSource'。但问题是现在datasource和entitymanager bean在启动时初始化。无论如何在春季配置它,以便在用户通过身份验证后进行初始化?

我能想到的另一个问题是如何处理并发。我把tenantId放在这个班级

public class ThreadLocalContextUtil {
 private static final ThreadLocal<String> contextHolder =
            new ThreadLocal<String>();

   public static void setTenantId(String tenantId) {
      Assert.notNull(tenantId, "customerType cannot be null");
      contextHolder.set(tenantId);
   }

   public static String getTenantId() {
      return (String) contextHolder.get();
   }

   public static void clearTenant() {
      contextHolder.remove();
   }
}

我能想到的解决方案是在数据源初始化后删除tenantId。那是对的吗?

1 个答案:

答案 0 :(得分:3)

我已经解决了类似的问题。我基于Spring TenantAwareDataSource实现了自己的AbstractDataSource。它从名为 tenantContext 的会话范围的bean中获取 tenantId 。每次处理传入请求时都会更新此Bean。它是通过使用Spring Security的安全过滤器完成的:

<security:http auto-config='false' >
    <security:custom-filter before="FIRST" ref="tenantFilter" />
    <!-- ...more security stuff... -->
</security:http>

我的TenantAwareDataSource在启动时初始化,但无关紧要,因为它是空的 - 它包含无租户数据源(例如池化的JDBC数据源或JPA实体管理器)。当第一次为所选租户调用getConnection()时,它们会被懒惰地创建。

因此,我的TenantAwareDataSource维护自己的动态数据源映射,而AbstractRoutingDataSource期望在启动时间内完成数据源映射的静态初始化。

在此article中阅读更详细的说明。