我试图通过带有弹簧启动和弹簧数据的歧视器实现来实现多租赁。
我上了一个抽象类来代表多租户实体。类似的东西:
@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