找回密码
 立即注册
首页 业界区 业界 .Net通过EFCore和仓储模式实现统一数据权限管控并且相关 ...

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

欤夤 昨天 19:00
基于EFCore实现统一数据权限管控

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

数据权限通常分为四个层级:所有数据、本部门数据、本部门及下属部门数据、本人数据。通过仓储模式可以统一封装这些查询逻辑。
具体实现可参考NetCoreKevin的Kevin.EntityFrameworkCore.Repository`和kevin.Permission服务模块:实现统一数据权限管控并且相关权限配置动态生成

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

项目地址:github:https://github.com/junkai-li/NetCoreKevin
Gitee: https://gitee.com/netkevin-li/NetCoreKevin
基础仓储接口设计

定义基础仓储接口,包含数据权限过滤方法:
  1. public interface IRepository<T> where T : class
  2. {
  3.     IQueryable<T> GetAll();
  4.     IQueryable<T> GetByDepartment(int departmentId);
  5.     IQueryable<T> GetByDepartmentWithChildren(int departmentId);
  6.     IQueryable<T> GetByUser(int userId);
  7. }
复制代码
实现数据权限过滤

在具体仓储实现中,通过EFCore的查询表达式实现不同级别的数据过滤:
  1. public class Repository<T> : IRepository<T> where T : class, IDataPermission
  2. {
  3.     private readonly DbContext _context;
  4.     private readonly ICurrentUser _currentUser;
  5.     public Repository(DbContext context, ICurrentUser currentUser)
  6.     {
  7.         _context = context;
  8.         _currentUser = currentUser;
  9.     }
  10.     public IQueryable<T> GetAll()
  11.     {
  12.         return _context.Set<T>().AsQueryable();
  13.     }
  14.     public IQueryable<T> GetByDepartment(int departmentId)
  15.     {
  16.         return _context.Set<T>().Where(x => x.DepartmentId == departmentId);
  17.     }
  18.     public IQueryable<T> GetByDepartmentWithChildren(int departmentId)
  19.     {
  20.         var departmentIds = GetChildDepartmentIds(departmentId);
  21.         return _context.Set<T>().Where(x => departmentIds.Contains(x.DepartmentId));
  22.     }
  23.     public IQueryable<T> GetByUser(int userId)
  24.     {
  25.         return _context.Set<T>().Where(x => x.CreatedBy == userId);
  26.     }
  27.     private List<int> GetChildDepartmentIds(int parentId)
  28.     {
  29.         // 递归获取所有子部门ID
  30.     }
  31. }
复制代码
实体接口设计

定义数据权限相关实体接口,确保实体包含必要字段:
  1. public interface IDataPermission
  2. {
  3.     int DepartmentId { get; set; }
  4.     int CreatedBy { get; set; }
  5. }
复制代码
动态权限查询扩展

创建扩展方法,根据用户权限动态选择查询范围:
  1. public static class RepositoryExtensions
  2. {
  3.     public static IQueryable<T> WithDataPermission<T>(this IRepository<T> repository, DataPermissionLevel level)
  4.         where T : class, IDataPermission
  5.     {
  6.         switch(level)
  7.         {
  8.             case DataPermissionLevel.All:
  9.                 return repository.GetAll();
  10.             case DataPermissionLevel.Department:
  11.                 return repository.GetByDepartment(currentUser.DepartmentId);
  12.             case DataPermissionLevel.DepartmentWithChildren:
  13.                 return repository.GetByDepartmentWithChildren(currentUser.DepartmentId);
  14.             case DataPermissionLevel.Owner:
  15.                 return repository.GetByUser(currentUser.UserId);
  16.             default:
  17.                 throw new ArgumentOutOfRangeException();
  18.         }
  19.     }
  20. }
复制代码
权限枚举定义

定义数据权限级别枚举:
  1. public enum DataPermissionLevel
  2. {
  3.     All,
  4.     Department,
  5.     DepartmentWithChildren,
  6.     Owner
  7. }
复制代码
使用示例

在服务层或控制器中使用数据权限过滤:
  1. public class EmployeeService
  2. {
  3.     private readonly IRepository<Employee> _repository;
  4.     private readonly ICurrentUser _currentUser;
  5.     public EmployeeService(IRepository<Employee> repository, ICurrentUser currentUser)
  6.     {
  7.         _repository = repository;
  8.         _currentUser = currentUser;
  9.     }
  10.     public List<Employee> GetEmployees(DataPermissionLevel level)
  11.     {
  12.         return _repository.WithDataPermission(level).ToList();
  13.     }
  14. }
复制代码
权限控制中间件

可以创建中间件自动设置当前用户的数据权限级别:
  1. public class DataPermissionMiddleware
  2. {
  3.     private readonly RequestDelegate _next;
  4.     public DataPermissionMiddleware(RequestDelegate next)
  5.     {
  6.         _next = next;
  7.     }
  8.     public async Task InvokeAsync(HttpContext context, ICurrentUser currentUser)
  9.     {
  10.         // 根据用户角色设置数据权限级别
  11.         currentUser.DataPermissionLevel = GetPermissionLevelFromClaims(context.User);
  12.         
  13.         await _next(context);
  14.     }
  15. }
复制代码
这种实现方式通过仓储模式统一了数据权限控制逻辑,使业务代码无需关心具体权限实现细节,只需指定权限级别即可自动过滤数据。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册