data filter是orm层动态注入where条件实现数据隔离的机制,典型应用包括软删除、租户隔离和部门范围控制;主流框架如ef core用hasqueryfilter、mybatis用拦截器、abp vnext用idatafilter特性支持。

权限数据隔离的核心,是让不同用户或角色在查询时“自动看不到不该看的数据”,而不是靠开发人员每次写SQL都手动加WHERE。Data Filter(数据过滤器)法正是通过框架层统一拦截和注入条件,实现零侵入、高一致性的隔离方案。
什么是Data Filter过滤器
它是一种运行在ORM或持久层的机制,能在生成SQL前动态追加WHERE子句,对查询结果做透明过滤。不是业务代码里的if判断,也不是SQL模板里硬编码的条件,而是注册一次、全局生效的规则。
典型例子:
- 软删除场景:所有查询自动加上
AND IsDeleted = 0 - 租户系统:自动补上
AND tenant_id = '当前租户ID' - 部门数据范围:查订单时自动追加
AND dept_id IN (1,5,8,12)(含子部门递归)
主流框架中的Data Filter实现方式
Entity Framework Plus(EF6/EF Core):用HasQueryFilter配置全局过滤器
- 支持Lambda表达式,类型安全
- 可结合
DbContext生命周期动态启用/禁用(如管理员绕过) - 注意:不适用于需要多字段组合或运行时动态值的复杂权限(如部门树)
MyBatis / MyBatis-Plus:基于拦截器(Interceptor)+ SQL解析
- 在
StatementHandler.prepare()阶段修改SQL,兼容原生Mapper、XML、LambdaQueryWrapper - 配合Druid或JSqlParser解析SQL结构,精准插入
AND条件到WHERE子句(避免拼错位置) - 支持注解驱动(如
@DataScope),按方法粒度开关
ABP vNext:内置IDataFilter接口,以特性(Attribute)方式声明
- 软删除(
ISoftDelete)、多租户()直接开箱即用
- 自定义过滤器继承
DataFilter<t>,在<code>OnModelCreating中注册 - 权限上下文由
ICurrentUser自动注入,无需手动传参
关键设计要点
只靠“加WHERE”远远不够,真正落地要解决三个问题:
- 动态值来源:当前用户所属部门ID、租户ID、角色类型等,必须从ThreadLocal、SecurityContext或Spring Security的Authentication中可靠提取
-
层级关系处理:父部门查子部门数据,需递归查出全部子ID(MySQL用
WITH RECURSIVE,PostgreSQL/Oracle有对应语法) -
例外与绕过:超级管理员、审计日志、导出报表等场景需临时关闭过滤器,EF可用
IgnoreQueryFilters(),MyBatis可通过注解标记或上下文开关
为什么比手动加WHERE更可靠
手动拼条件容易遗漏、难维护、测试覆盖不全;而Data Filter是统一入口:
- 连
Count()、Any()、关联查询(Include)都会被自动过滤 - 分页插件(PageHelper、EF的Skip/Take)仍能正确计算总数
- 避免因Mapper XML漏写、Lambda条件写错、动态SQL未覆盖导致的数据越权











