java 使用spring-boot & spring-data全局启用hibernate filter

j2cgzkjk  于 2023-05-12  发布在  Java
关注(0)|答案(2)|浏览(105)

我正在尝试使用Sping Boot 和Spring Data实现多租户鉴别器实现。
我创建了一个抽象类来表示一个多租户实体。类似于这个的东西:

@MappedSuperclass
@FilterDefs({@FilterDef(name = "multi-tenant", parameters = {@ParamDef(name = "tenant", type = "string")})})
@Filter(name = "multi-tenant", condition = "tenant = :tenant")
public abstract class MultiTenantEntity extends GenericEntity {
    @Transient
    private transient String savedTenant;

    @PostLoad
    private void onLoad() throws Exception {
        this.savedTenant = this.tenant;
        onEntityModification();
    }

    @PrePersist
    private void onPersist() {
        if (getId() == null || getId().equals(0l)) {
            tenant = SecurityUtil.getCurrentTenant();
        }
    }

    @PreUpdate
    @PreRemove
    private void onEntityModification() throws Exception {
        String currentTenant = SecurityUtil.getCurrentTenant();

        if (!currentTenant.equals(tenant) || !savedTenant.equals(tenant)) {
            throw new Exception();
        }
    }

    @NotNull
    private String tenant;

    public String getTenant() {
        return tenant;
    }
}

如何全局开启***多租户***hibernate过滤器?

jv4diomz

jv4diomz1#

在我们的应用程序中,使用hibernate过滤器可以很容易地实现多租户,甚至可以实现行级ACL。您可以使用AOP和数据库中可配置的不同过滤器来代替discriminator。在调用基于访问用户的请求方法之前,应用启用休眠会话过滤器的过滤器并执行请求,在成功处理请求之后,禁用过滤器。就是这样。使用这种方式,你可以添加任何数量的过滤器到任何数量的实体,这些实体将由当前用户操作,你可以用它来做完美的资源(实体和CRUD)管理。

lsmepo6l

lsmepo6l2#

您可以使用Spring HandlerInterceptor沿着Spring的Open Session in View来实现这一点:

确保打开View中的Open Session

application.yml

spring:
  jpa:
    open-in-view: true

添加HandlerInterceptor

@Component
public class HibernateInterceptor implements HandlerInterceptor {

    @Autowired
    private EntityManager entityManager;

    @Override
    @Transactional
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Session session = entityManager.unwrap(Session.class);
        session.enableFilter("multi-tenant")
               .setParameter("tenant", "my-tenant-value");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        Session session = entityManager.unwrap(Session.class);
        session.disableFilter("multi-tenant");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // This method is called after the response has been sent to the client
    }
}

配置HandlerInterceptor

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private HibernateInterceptor hibernateInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(hibernateInterceptor).order(Ordered.LOWEST_PRECEDENCE);
    }
}

关键是确保HandlerInterceptor在Spring的OpenEntityManagerInViewInterceptor之后运行-这可以通过将顺序设置为Ordered.LOWEST_PRECEDENCE来实现

相关问题