# 只显示用户有权查看的数据

# 概述

本功能用于实现应用数据的访问控制,确保应用只列出当前登录用户有权查看的数据,而不是全部数据。

# 一、示例演示:客户名录数据隔离

# 演示路径

  • 访问地址:应用门户
  • 模块名称:仅列出可见数据

操作步骤

  1. 进入应用门户
  2. 找到“仅列出可见数据”模块
  3. 点击进入客户登记应用

# 业务处理效果

全部客户页签

  • 显示所有客户数据,共3条记录
  • 登记人分别为:张三、李四、史蒂夫

我的客户页签(当前登录用户:史蒂夫):

  • 仅显示1条数据
  • 只显示史蒂夫本人登记的客户
  • 别人的客户看不到

# 二、实现方法

# 前台配置

文件路径Web项目\WEB\Apps\Navigator\Samples\ConceptController.cs

// 第67行:客户名录模块,包含2个标签页
new {
    id = "Sample.客户名录",
    text = "仅列出可见数据",
    glyph = 0xea9c,
    expanded = true,
    activeTab = 0,
    tabs = new object[]{
        // 第75-77行:全部客户页签
        new {
            id = "Sample.客户名录.all",
            text = "全部客户",
            xclass = "Apps.samples.CustomersAll"
        },
        // 第80-82行:我的客户页签
        new {
            id = "Sample.客户名录.self",
            text = "我的客户",
            xclass = "Apps.samples.CustomersSelf"
        }
    }
}

前台脚本文件wwwroot\Apps\Sample\CustomersSelf.js

// 第4行:指定后台服务地址
service: "app/samples/customers/self"

# 后台服务实现

文件路径Web项目\Apps\Controllers\SampleCustomersSelfController.cs

// 第27-30行:重载ApplyDataIsolationFilter实现数据隔离
protected override IQueryable<SampleCustomer> ApplyDataIsolationFilter(
    IQueryable<SampleCustomer> query, 
    HttpContext httpContext)
{
    // 添加过滤条件:只显示当前登录用户登记的数据
    return query.Where(x => x.RegisterBy == authService.LoginUserAccount);
}

代码说明

  • ApplyDataIsolationFilter:列表数据处理链中的钩子函数,用于附加额外的过滤条件
  • RegisterBy:客户资料登记人字段
  • authService.LoginUserAccount:当前登录用户账号

# 对比:全部客户服务(无隔离)

文件路径Web项目\Apps\Controllers\SampleCustomersAllController.cs

// 未重载ApplyDataIsolationFilter函数
// 因此不附加任何过滤条件,显示全部数据

# 三、核心原理与配置

# 核心钩子

特性 说明
函数名称 ApplyDataIsolationFilter
所在位置 ListController<T>中的虚函数
调用时机 获取列表数据时自动调用
作用 为查询对象附加额外的过滤条件

# 配置步骤

  1. 找到对应控制器:如SampleCustomersSelfController.cs
  2. 重载钩子函数:重写ApplyDataIsolationFilter方法
  3. 添加过滤条件:在方法中添加EF Core支持的查询条件
  4. 返回过滤结果:返回添加了条件的IQueryable

# 关键要点

  • 钩子函数:专门为数据隔离设计的扩展点
  • 灵活过滤:支持任何EF Core支持的查询条件
  • 用户信息:通过authService获取当前登录用户

# 四、扩展应用

# 复杂过滤示例

protected override IQueryable<SampleCustomer> ApplyDataIsolationFilter(
    IQueryable<SampleCustomer> query, 
    HttpContext httpContext)
{
    var authService = httpContext.RequestServices.GetRequiredService<IAuthService>();
    var currentUser = authService.LoginUserAccount;
    var currentUserRole = authService.LoginUserRole;
    
    // 管理员查看全部数据
    if (currentUserRole == "Admin")
        return query;
    
    // 部门经理查看本部门数据
    if (currentUserRole == "Manager")
    {
        var department = authService.LoginUserDepartment;
        return query.Where(x => x.Department == department);
    }
    
    // 普通员工只查看自己数据
    return query.Where(x => x.RegisterBy == currentUser);
}

# 五、常见应用场景

场景 过滤条件
个人数据 x.RegisterBy == currentUser
部门内可见 x.Department == user.Department
领导查看下级 x.RegisterBy.In(user.Subordinates)

# 六、注意事项

  1. 函数重载:确保正确重载ApplyDataIsolationFilter函数
  2. 过滤条件:可以使用任何EF Core支持的条件
  3. 用户信息:通过authService获取当前登录用户
  4. 字段对应:确保字段名称与实体类属性一致

# 七、总结

数据隔离的实现非常便捷:

  • 做法简单:重载ApplyDataIsolationFilter函数,给查询附加额外的条件
  • 一行代码:只需添加一行过滤条件
  • 灵活扩展:可以附加任何EF Core支持的条件
  • 常见需求:满足仅自己可见、部门内可见、领导查看下级等需求

对于部门内可见、领导可查看下级填写的数据等更为复杂的过滤需求,将在本章的进阶中讲解。