基于ASP.NET Identity实现多用户独立卡牌收藏系统的方案咨询
绝对适合!ASP.NET Identity 就是为这类用户数据隔离场景量身打造的
没错,ASP.NET Identity 完全能满足你的需求——它自带成熟的用户注册、登录、身份验证体系,而且天然支持将业务数据与用户ID绑定,实现不同用户数据完全隔离的效果,就像你说的Gmail那种机制。
接下来我基于你给出的现有模型,一步步给你落地的实现方案:
第一步:给业务模型添加用户关联
首先要让Card和Deck都与ASP.NET Identity的用户(默认是ApplicationUser)建立关联,这样每张卡牌、每个卡组都能明确归属到某个用户。修改你的模型:
修改后的Card类
public class Card { public int Id { get; set; } public string Name { get; set; } public int? Atk { get; set; } public int? Def { get; set; } public string Desc {get; set;} public int? Level { get; set; } public string Type { get; set; } public string Attribute { get; set; } // 添加用户关联字段 public string UserId { get; set; } public virtual ApplicationUser User { get; set; } [DisplayName("Image")] public virtual List<Image> Card_Images { get; set; } public virtual List<Deck> Decks { get; set; } }
修改后的Deck类
public class Deck { public int Id { get; set; } // 统一成大写Id符合C#命名规范 public string Name { get; set; } public string Notes { get; set; } // 添加用户关联字段 public string UserId { get; set; } public virtual ApplicationUser User { get; set; } [DisplayName("Card")] public virtual List<Card> Cards { get; set; } // 改成复数Cards更符合语义 }
第二步:配置DbContext中的关系
在你的DbContext(比如AppDbContext)中,需要配置这些关联关系,确保EF Core能正确生成数据库表和外键:
public class AppDbContext : IdentityDbContext<ApplicationUser> { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<Card> Cards { get; set; } public DbSet<Deck> Decks { get; set; } public DbSet<Image> Images { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 必须调用,确保Identity表正常生成 // 配置Card与User的关系:一个用户拥有多个卡牌 modelBuilder.Entity<Card>() .HasOne(c => c.User) .WithMany(u => u.Cards) // 需要在ApplicationUser中添加对应导航属性 .HasForeignKey(c => c.UserId) .OnDelete(DeleteBehavior.Cascade); // 用户删除时,关联卡牌一并删除 // 配置Deck与User的关系:一个用户拥有多个卡组 modelBuilder.Entity<Deck>() .HasOne(d => d.User) .WithMany(u => u.Decks) // 需要在ApplicationUser中添加对应导航属性 .HasForeignKey(d => d.UserId) .OnDelete(DeleteBehavior.Cascade); // 配置Deck与Card的多对多关系,自动生成中间关联表 modelBuilder.Entity<Deck>() .HasMany(d => d.Cards) .WithMany(c => c.Decks) .UsingEntity(j => j.ToTable("DeckCards")); } }
别忘了在ApplicationUser类中添加对应的导航属性:
public class ApplicationUser : IdentityUser { public virtual List<Card> Cards { get; set; } = new List<Card>(); public virtual List<Deck> Decks { get; set; } = new List<Deck>(); }
第三步:修改数据访问逻辑,确保用户只能访问自己的数据
在你的控制器或服务层中,所有查询、添加、修改操作都要带上当前登录用户的ID,过滤出属于自己的数据:
示例:CardController中的查询与创建逻辑
public class CardController : Controller { private readonly AppDbContext _context; private readonly UserManager<ApplicationUser> _userManager; public CardController(AppDbContext context, UserManager<ApplicationUser> userManager) { _context = context; _userManager = userManager; } // 只显示当前用户的卡牌 public async Task<IActionResult> Index() { var currentUserId = _userManager.GetUserId(User); var userCards = await _context.Cards .Include(c => c.Card_Images) .Where(c => c.UserId == currentUserId) .ToListAsync(); return View(userCards); } // 添加卡牌时自动关联当前用户 [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("Id,Name,Atk,Def,Desc,Level,Type,Attribute")] Card card) { if (ModelState.IsValid) { card.UserId = _userManager.GetUserId(User); // 绑定当前用户ID _context.Add(card); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(card); } }
示例:确保用户只能修改自己的卡牌
在Edit/Delete等操作中,先验证资源是否属于当前用户:
public async Task<IActionResult> Edit(int? id) { if (id == null) return NotFound(); var currentUserId = _userManager.GetUserId(User); var card = await _context.Cards.FirstOrDefaultAsync(c => c.Id == id && c.UserId == currentUserId); if (card == null) return NotFound(); // 资源不属于当前用户时返回404 return View(card); }
第四步:添加授权保护
给所有需要登录才能访问的控制器或方法添加[Authorize]属性,确保只有登录用户才能操作:
[Authorize] public class CardController : Controller { // ... 控制器逻辑 } [Authorize] public class DeckController : Controller { // ... 控制器逻辑 }
额外的最佳实践
- 避免直接暴露用户ID:永远不要让前端传递用户ID来查询/修改数据,始终通过
UserManager.GetUserId(User)获取当前用户ID,防止恶意用户篡改数据。 - 数据验证:在服务层或控制器中,对所有修改/删除操作添加权限验证,确保用户只能操作自己的数据。
- 更新数据库:修改模型后,执行EF Core迁移命令更新数据库:
Add-Migration AddUserRelations Update-Database
这样一套下来,就能实现你想要的效果:新用户注册登录后,只能看到和管理自己的卡牌、卡组,不同用户的数据完全隔离。
内容的提问来源于stack exchange,提问作者dros
相关产品推荐
相关产品推荐

