.NET Core Identity用户分组功能实现代码合理性咨询
你的整体设计思路是对的,参照Identity的Roles、UserRoles的多对多关联逻辑来实现用户组是合理的,但当前代码还有几处需要调整的地方,才能完全匹配你的业务需求以及EF Core的开发规范:
- 中间表
UserGroups缺少显式的外键和主键声明:仅靠导航属性依赖EF Core隐式生成字段,会出现字段名不可控、后续关联查询不方便的问题,参考Identity的UserRoles设计,需要给中间表显式声明两个外键字段,并将二者设为联合主键。 - 两端实体缺少对应的集合导航属性:
Groups和ApplicationUser都没有关联UserGroups的集合属性,无法直接实现「查某用户所属所有组」「查某组所有成员」这类常用操作。 - 资源表未适配组共享逻辑:你当前的
GSMSite只关联了ApplicationUser,要实现组内资源共享,需要给资源表新增GroupId外键,支持资源归属于组。 - 命名不符合C#规范:类名建议使用单数形式,
Groups改为Group、UserGroups改为UserGroup。
1. 调整后的实体类代码
// 用户组实体 public class Group { public Guid Id { get; set; } [MaxLength(30)] public string Name { get; set; } // 适配邀请功能的扩展字段:组创建人、创建时间 public string CreatorId { get; set; } public virtual ApplicationUser Creator { get; set; } public DateTime CreatedTime { get; set; } = DateTime.UtcNow; // 组内成员导航 public virtual ICollection<UserGroup> UserGroups { get; set; } // 组归属的资源导航 public virtual ICollection<GSMSite> GSMSites { get; set; } } // 用户-组关联中间表 public class UserGroup { // 联合主键,需在DbContext中配置 public string ApplicationUserId { get; set; } public Guid GroupId { get; set; } // 导航属性 public virtual ApplicationUser ApplicationUser { get; set; } public virtual Group Group { get; set; } // 扩展字段:加入时间、是否为组管理员(支持组内权限区分) public DateTime JoinedTime { get; set; } = DateTime.UtcNow; public bool IsGroupAdmin { get; set; } = false; } // 调整后的用户实体 public class ApplicationUser : IdentityUser { [MaxLength(30)] public string FirstName { get; set; } [MaxLength(30)] public string LastName { get; set; } [MaxLength(100)] public string Company { get; set; } [MaxLength(30)] public string Telephone { get; set; } [MaxLength(15)] public string Postcode { get; set; } public DateTime Created { get; set; } = DateTime.UtcNow; public DateTime PasswordResetTime { get; set; } = DateTime.UtcNow; public bool PasswordReset { get; set; } = false; // 个人专属资源 public virtual ICollection<GSMSite> GSMSites { get; set; } // 用户所属的所有组 public virtual ICollection<UserGroup> UserGroups { get; set; } }
2. DbContext关联配置
需要在你的Identity自定义DbContext的OnModelCreating方法中添加以下配置,声明中间表的联合主键和关联关系:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 配置UserGroup联合主键 modelBuilder.Entity<UserGroup>() .HasKey(ug => new { ug.ApplicationUserId, ug.GroupId }); // 配置用户和组的关联关系 modelBuilder.Entity<UserGroup>() .HasOne(ug => ug.ApplicationUser) .WithMany(u => u.UserGroups) .HasForeignKey(ug => ug.ApplicationUserId) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity<UserGroup>() .HasOne(ug => ug.Group) .WithMany(g => g.UserGroups) .HasForeignKey(ug => ug.GroupId) .OnDelete(DeleteBehavior.Cascade); }
3. 资源鉴权逻辑调整
后续判断用户是否有权限访问某GSMSite资源时,除了判断资源的ApplicationUserId是否等于当前登录用户ID,还要额外判断:如果资源的GroupId不为空,且当前用户的所属组列表中包含该GroupId,则允许访问。
内容的提问来源于stack exchange,提问作者A Houghton
相关产品推荐
相关产品推荐

