Galosys.Foundation.DataPermission
26.7.26.1
dotnet add package Galosys.Foundation.DataPermission --version 26.7.26.1
NuGet\Install-Package Galosys.Foundation.DataPermission -Version 26.7.26.1
<PackageReference Include="Galosys.Foundation.DataPermission" Version="26.7.26.1" />
<PackageVersion Include="Galosys.Foundation.DataPermission" Version="26.7.26.1" />
<PackageReference Include="Galosys.Foundation.DataPermission" />
paket add Galosys.Foundation.DataPermission --version 26.7.26.1
#r "nuget: Galosys.Foundation.DataPermission, 26.7.26.1"
#:package Galosys.Foundation.DataPermission@26.7.26.1
#addin nuget:?package=Galosys.Foundation.DataPermission&version=26.7.26.1
#tool nuget:?package=Galosys.Foundation.DataPermission&version=26.7.26.1
Galosys.Foundation.DataPermission
可扩展的行级数据权限框架,与 EF Core 全局查询过滤器深度集成。支持部门级、个人级、角色数据范围三种过滤策略,通过标记接口自动识别实体维度,零侵入实现数据隔离。
快速开始
1. 安装
在项目中引用 Galosys.Foundation.DataPermission(依赖 Core + EntityFrameworkCore)。
2. 注册服务(最小配置)
// Program.cs / Startup.cs
using Galosys.Foundation.DataPermission;
services.AddDataPermission(options =>
{
options.AddFilter<DeptDataPermissionFilter>(); // 部门级过滤
options.AddFilter<PersonalDataPermissionFilter>(); // 个人级过滤
options.AddFilter<RoleDataScopeFilter>(); // 角色数据范围
});
3. 实现权限上下文
框架通过 IDataPermissionContext 获取当前用户信息,需由中台或业务层实现:
using Galosys.Foundation.DataPermission;
public class JwtDataPermissionContext : IDataPermissionContext
{
public long UserId { get; } // 当前用户ID
public string? UserName { get; } // 当前用户名称
public long DeptId { get; } // 当前用户所属部门ID
public IReadOnlyList<long> RoleIds { get; } // 当前用户角色ID列表
public DataScope DataScope { get; } // 数据权限范围
public IReadOnlyList<long> DeptIds { get; } // 授权可见的部门ID列表(含子部门树)
public JwtDataPermissionContext(ClaimsPrincipal user)
{
UserId = user.FindFirst("sub")?.Let(long.Parse) ?? 0;
UserName = user.FindFirst("name")?.Value;
DeptId = user.FindFirst("dept_id")?.Let(long.Parse) ?? 0;
RoleIds = user.FindAll("role_id").Select(c => long.Parse(c.Value)).ToList();
DataScope = user.FindFirst("data_scope")?.Let(Enum.Parse<DataScope>) ?? DataScope.Personal;
DeptIds = user.FindAll("dept_ids").Select(c => long.Parse(c.Value)).ToList();
}
}
注册上下文(Scoped 生命周期,每个请求一份):
using Galosys.Foundation.DataPermission;
using Microsoft.AspNetCore.Http;
services.AddScoped<IDataPermissionContext>(sp =>
{
var httpContext = sp.GetRequiredService<IHttpContextAccessor>().HttpContext;
if (httpContext == null) return null!; // BackgroundService 场景优雅降级,无过滤器生效
return new JwtDataPermissionContext(httpContext.User);
});
4. 实体标记接口
为实体添加标记接口即可自动参与数据权限过滤:
using Galosys.Foundation.DataPermission;
// 同时支持部门级和个人级过滤
public class Order : FullEntity<long>, IDataPermissionDept, IDataPermissionCreator
{
public long DeptId { get; set; } // 部门ID(IDataPermissionDept 要求)
public long CreatorId { get; set; } // 创建人ID(IDataPermissionCreator 要求)
}
完成以上配置后,所有 EF Core 查询自动附加数据权限过滤,无需手动编写 Where 条件。
实体标记接口
| 接口 | 属性 | 说明 |
|---|---|---|
IDataPermissionDept |
DeptId |
实体实现后支持按部门维度过滤 |
IDataPermissionCreator |
CreatorId |
实体实现后支持按创建人维度过滤 |
实体可单独实现一个接口,也可同时实现两个。框架通过 isAssignable 检测自动选择对应的过滤器。
DataScope 数据范围
| 值 | 名称 | 过滤行为 |
|---|---|---|
All |
全部数据 | 不添加任何过滤 |
Dept |
本部门 | e.DeptId == 当前部门ID |
DeptAndChild |
本部门及下属 | DeptIds.Contains(e.DeptId) |
Personal |
仅本人 | e.CreatorId == 当前用户ID |
Custom |
自定义 | DeptIds.Contains(e.DeptId)(使用自定义的部门列表) |
内置过滤器详解
DeptDataPermissionFilter(Order = 10)
部门级过滤器,处理 IDataPermissionDept 实体。
| DataScope | 行为 |
|---|---|
All |
不过滤 |
Dept |
e => e.DeptId == context.DeptId |
DeptAndChild / Custom |
e => context.DeptIds.Contains(e.DeptId) |
Personal |
不过滤(由 PersonalDataPermissionFilter 处理) |
PersonalDataPermissionFilter(Order = 20)
个人级过滤器,仅在 DataScope.Personal 时生效,处理 IDataPermissionCreator 实体。
| DataScope | 行为 |
|---|---|
Personal |
e => e.CreatorId == context.UserId |
| 其他 | 不过滤 |
RoleDataScopeFilter(Order = 5)
角色数据范围过滤器,优先级最高(Order 最小)。当 DataScope.Personal 且实体实现了 IDataPermissionCreator 时,按创建人过滤;DataScope.All 时不过滤。
三个过滤器通过
AndAlso组合,最终生成一个统一的过滤表达式注入 EF Core 全局查询过滤器。
自定义过滤器
实现 IDataPermissionFilter 接口并注册即可扩展:
using Galosys.Foundation.DataPermission;
using System.Linq.Expressions;
/// <summary>
/// 按业务线过滤示例
/// </summary>
public class BusinessLineFilter : IDataPermissionFilter
{
public int Order => 15; // 执行顺序,介于 Dept(10) 和 Personal(20) 之间
public Expression<Func<TEntity, bool>>? BuildFilter<TEntity>(IDataPermissionContext context)
where TEntity : class
{
// 仅对实现了 IBusinessLine 接口的实体生效
if (!typeof(IBusinessLine).IsAssignableFrom(typeof(TEntity)))
return null;
// 从上下文扩展信息中获取业务线
var parameter = Expression.Parameter(typeof(TEntity), "e");
var blProp = Expression.Property(parameter, nameof(IBusinessLine.BusinessLineId));
var body = Expression.Equal(blProp, Expression.Constant(context.DeptId));
return Expression.Lambda<Func<TEntity, bool>>(body, parameter);
}
}
注册:
services.AddDataPermission(options =>
{
options.AddFilter<RoleDataScopeFilter>();
options.AddFilter<DeptDataPermissionFilter>();
options.AddFilter<BusinessLineFilter>(); // 自定义过滤器
options.AddFilter<PersonalDataPermissionFilter>();
});
架构说明
┌──────────────────────────────────────────────────────────┐
│ EF Core DbContext │
│ ┌────────────────────────────────────────────────────┐ │
│ │ IGlobalFilterProvider 体系 │ │
│ │ ┌─────────────────────┐ ┌──────────────────────┐ │ │
│ │ │ DefaultGlobal │ │ DataPermission │ │ │
│ │ │ FilterProvider │ │ FilterProvider │ │ │
│ │ │ (软删除/多租户/多应用)│ │ (数据权限桥接) │ │ │
│ │ └─────────────────────┘ └──────────┬───────────┘ │ │
│ └───────────────────────────────────────┼─────────────┘ │
└──────────────────────────────────────────┼───────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ IDataPermissionResolver │
│ (DataPermissionResolver) │
│ │
│ 聚合所有 IDataPermissionFilter,按 Order 排序, │
│ 通过 AndAlso 合并为统一过滤表达式 │
│ │
│ ┌───────────┐ ┌──────────────────┐ ┌─────────────────┐ │
│ │ RoleData │ │ DeptData │ │ PersonalData │ │
│ │ ScopeFilter│ │ PermissionFilter │ │ PermissionFilter│ │
│ │ (Order=5) │ │ (Order=10) │ │ (Order=20) │ │
│ └───────────┘ └──────────────────┘ └─────────────────┘ │
└───────────────────────────┬──────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ IDataPermissionContext(Scoped) │
│ UserId │ UserName │ DeptId │ RoleIds │ DataScope │ DeptIds │
│ 由中台实现,通常从 JWT / Session 中解析 │
└──────────────────────────────────────────────────────────┘
核心类型一览
| 类型 | 职责 |
|---|---|
IDataPermissionContext |
当前用户权限上下文(UserId、DeptId、DataScope 等) |
IDataPermissionResolver |
聚合所有过滤器,生成最终过滤表达式 |
IDataPermissionFilter |
单维度过滤器接口,自定义过滤器的扩展点 |
DataPermissionOptions |
配置项,通过 AddFilter<T>() 注册过滤器 |
DataPermissionFilterProvider |
桥接 IDataPermissionResolver 到 EF Core IGlobalFilterProvider |
DataScope |
数据范围枚举(All / Dept / DeptAndChild / Personal / Custom) |
生命周期
| 服务 | 生命周期 | 说明 |
|---|---|---|
IDataPermissionResolver |
Singleton | 无状态,可安全复用 |
IDataPermissionFilter |
Transient | 每次解析创建新实例,支持多过滤器并行 |
IDataPermissionContext |
Scoped | 每个请求一份,由业务层注册 |
IGlobalFilterProvider |
Singleton | 每次查询时通过 IServiceProvider 获取 Scoped 上下文 |
优雅降级
IDataPermissionContext未注册或解析为null时(如后台服务、迁移场景),所有过滤器自动跳过,不添加任何限制- 实体未实现对应标记接口时,该维度的过滤器自动跳过
- 框架不抛异常,确保非 Web 场景正常运行
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Galosys.Foundation.Core (>= 26.7.26.1)
- Galosys.Foundation.EntityFrameworkCore (>= 26.7.26.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 26.7.26.1 | 0 | 7/25/2026 |
| 26.7.25.1 | 0 | 7/25/2026 |
| 26.7.24.2 | 34 | 7/24/2026 |
| 26.7.24.1 | 36 | 7/24/2026 |
| 26.7.22.1 | 50 | 7/23/2026 |
| 26.7.21.1 | 85 | 7/21/2026 |
| 26.7.20.2 | 83 | 7/20/2026 |
| 26.7.20.1 | 81 | 7/20/2026 |
| 26.7.19.3 | 83 | 7/19/2026 |
| 26.7.19.2 | 84 | 7/19/2026 |
| 26.7.19.1 | 80 | 7/19/2026 |
| 26.7.18.2 | 85 | 7/18/2026 |
| 26.7.18.1 | 79 | 7/18/2026 |
| 26.7.17.1 | 85 | 7/17/2026 |
| 26.7.14.1 | 89 | 7/14/2026 |
| 26.7.13.1 | 88 | 7/13/2026 |
| 26.7.12.1 | 92 | 7/12/2026 |
| 26.7.11.1 | 90 | 7/11/2026 |
| 26.7.10.2 | 94 | 7/10/2026 |
| 26.7.10.1 | 92 | 7/10/2026 |