.Net通过EFCore和仓储模式实现统一数据权限管控并且相关权限配置动态生成

基于EFCore实现统一数据权限管控

在.NET应用中,通过EFCore和仓储模式实现数据权限管控,可以按照以下方式设计:

数据权限层级定义

数据权限通常分为四个层级:所有数据、本部门数据、本部门及下属部门数据、本人数据。通过仓储模式可以统一封装这些查询逻辑。

具体实现可参考NetCoreKevin的Kevin.EntityFrameworkCore.Repository`和kevin.Permission服务模块:实现统一数据权限管控并且相关权限配置动态生成

基于NET构建的现代化AI智能体Saas企业级架构:

项目地址:github:https://github.com/junkai-li/NetCoreKevin

Gitee: https://gitee.com/netkevin-li/NetCoreKevin

基础仓储接口设计

定义基础仓储接口,包含数据权限过滤方法:

csharp 复制代码
public interface IRepository<T> where T : class
{
    IQueryable<T> GetAll();
    IQueryable<T> GetByDepartment(int departmentId);
    IQueryable<T> GetByDepartmentWithChildren(int departmentId);
    IQueryable<T> GetByUser(int userId);
}
实现数据权限过滤

在具体仓储实现中,通过EFCore的查询表达式实现不同级别的数据过滤:

csharp 复制代码
public class Repository<T> : IRepository<T> where T : class, IDataPermission
{
    private readonly DbContext _context;
    private readonly ICurrentUser _currentUser;

    public Repository(DbContext context, ICurrentUser currentUser)
    {
        _context = context;
        _currentUser = currentUser;
    }

    public IQueryable<T> GetAll()
    {
        return _context.Set<T>().AsQueryable();
    }

    public IQueryable<T> GetByDepartment(int departmentId)
    {
        return _context.Set<T>().Where(x => x.DepartmentId == departmentId);
    }

    public IQueryable<T> GetByDepartmentWithChildren(int departmentId)
    {
        var departmentIds = GetChildDepartmentIds(departmentId);
        return _context.Set<T>().Where(x => departmentIds.Contains(x.DepartmentId));
    }

    public IQueryable<T> GetByUser(int userId)
    {
        return _context.Set<T>().Where(x => x.CreatedBy == userId);
    }

    private List<int> GetChildDepartmentIds(int parentId)
    {
        // 递归获取所有子部门ID
    }
}
实体接口设计

定义数据权限相关实体接口,确保实体包含必要字段:

csharp 复制代码
public interface IDataPermission
{
    int DepartmentId { get; set; }
    int CreatedBy { get; set; }
}
动态权限查询扩展

创建扩展方法,根据用户权限动态选择查询范围:

csharp 复制代码
public static class RepositoryExtensions
{
    public static IQueryable<T> WithDataPermission<T>(this IRepository<T> repository, DataPermissionLevel level) 
        where T : class, IDataPermission
    {
        switch(level)
        {
            case DataPermissionLevel.All:
                return repository.GetAll();
            case DataPermissionLevel.Department:
                return repository.GetByDepartment(currentUser.DepartmentId);
            case DataPermissionLevel.DepartmentWithChildren:
                return repository.GetByDepartmentWithChildren(currentUser.DepartmentId);
            case DataPermissionLevel.Owner:
                return repository.GetByUser(currentUser.UserId);
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}
权限枚举定义

定义数据权限级别枚举:

csharp 复制代码
public enum DataPermissionLevel
{
    All,
    Department,
    DepartmentWithChildren,
    Owner
}
使用示例

在服务层或控制器中使用数据权限过滤:

csharp 复制代码
public class EmployeeService
{
    private readonly IRepository<Employee> _repository;
    private readonly ICurrentUser _currentUser;

    public EmployeeService(IRepository<Employee> repository, ICurrentUser currentUser)
    {
        _repository = repository;
        _currentUser = currentUser;
    }

    public List<Employee> GetEmployees(DataPermissionLevel level)
    {
        return _repository.WithDataPermission(level).ToList();
    }
}
权限控制中间件

可以创建中间件自动设置当前用户的数据权限级别:

csharp 复制代码
public class DataPermissionMiddleware
{
    private readonly RequestDelegate _next;

    public DataPermissionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, ICurrentUser currentUser)
    {
        // 根据用户角色设置数据权限级别
        currentUser.DataPermissionLevel = GetPermissionLevelFromClaims(context.User);
        
        await _next(context);
    }
}

这种实现方式通过仓储模式统一了数据权限控制逻辑,使业务代码无需关心具体权限实现细节,只需指定权限级别即可自动过滤数据。

相关推荐
helloworddm4 小时前
CalculateGrainDirectoryPartition
服务器·c#·.net
步步为营DotNet5 小时前
深度剖析.NET中HttpClient的请求重试机制:可靠性提升与实践优化
开发语言·php·.net
ChaITSimpleLove5 小时前
使用 .net10 构建 AI 友好的 RSS 订阅机器人
人工智能·.net·mcp·ai bot·rss bot
专注VB编程开发20年5 小时前
vb.net宿主程序通过统一接口直接调用,命名空间要一致
服务器·前端·.net
ChaITSimpleLove20 小时前
基于 .NET Garnet 1.0.91 实现高性能分布式锁(使用 Lua 脚本)
分布式·.net·lua
用户4488466710601 天前
.NET进阶——深入理解线程(2)Thread入门到精通
c#·.net
一个帅气昵称啊1 天前
.Net——AI智能体开发基于 Microsoft Agent Framework 实现第三方聊天历史存储
人工智能·microsoft·.net