使用弹簧启动和弹簧数据全局启用休眠过滤器



我试图通过带有弹簧启动和弹簧数据的歧视器实现来实现多租赁。

我上了一个抽象类来代表多租户实体。类似的东西:

@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 filter在全球范围内?

使用Hibernate过滤器,即使在我们的应用程序中也可以使用ROW级别ACL,它易于实现。您可以在DB中使用AOP和不同的过滤器,而不是歧视器。在调用您的请求方法之前,基于访问用户应用启用Hibernate Session过滤器的过滤器,并在成功请求处理后,请求处理过滤器。就是这样。使用这种方式,您可以将任何数量的过滤器添加到将由当前用户操作的任何数字实体中,并且您可以使用此操作。

您可以使用Spring HandlerInterceptor以及春季的开放会话来完成此操作:

确保启用视图中的打开会话

application.yml

spring:
  jpa:
    open-in-view: true

添加一个处理程序

@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在春季OpenEntityManagerInViewInterceptor之后运行 - 这是通过将订单设置为Ordered.LOWEST_PRECEDENCE

来完成的

最新更新