You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Entity Framework中用户关联项目的查询、创建及用户ID安全获取方式咨询

解决你的ASP.NET Identity多对多项目关联问题

嘿,针对你提出的三个问题,我结合ASP.NET Identity和EF Core的最佳实践来给你解答:

1. 筛选当前用户所属的所有项目

首先,你需要确保EF Core正确配置了Project和AppUser之间的多对多关系——如果还没配置,记得在你的DbContext的OnModelCreating方法里添加这段代码:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder); // 不要忘记调用Identity的基础配置

    // 配置多对多关系,生成中间表ProjectUsers
    modelBuilder.Entity<Project>()
        .HasMany(p => p.users)
        .WithMany(u => u.projects)
        .UsingEntity(j => j.ToTable("ProjectUsers"));
}

接下来修改你的Index方法,利用传递的id参数筛选项目。另外一定要加权限验证,防止用户篡改URL中的id访问他人数据:

[Authorize]
public IActionResult Index(string id)
{
    // 获取当前登录用户的ID,用于验证传入的id是否合法
    var currentUserId = _userManager.GetUserId(User);
    if (id != currentUserId)
    {
        return Forbid(); // 拒绝越权访问
    }

    // 从UnitOfWork中查询包含当前用户的项目
    var userProjects = _unitOfWork.Project
        .GetAll(includeProperties: "users") // 确保加载关联的用户集合
        .Where(project => project.users.Any(user => user.Id == id))
        .ToList();

    return View(userProjects);
}

如果你的UnitOfWork的GetAll方法不支持指定关联属性加载,也可以直接使用DbContext:

var userProjects = _context.Projects
    .Include(p => p.users)
    .Where(p => p.users.Any(u => u.Id == id))
    .ToList();

2. 创建关联当前用户的项目

在POST的Create方法中,你需要先验证传入的id是否为当前登录用户,然后将用户与新建项目关联:

[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Project project, string id)
{
    if (!ModelState.IsValid)
    {
        return View(project);
    }

    var currentUserId = _userManager.GetUserId(User);
    if (id != currentUserId)
    {
        return Forbid();
    }

    // 获取当前用户实体
    var currentUser = _unitOfWork.AppUser.Get(u => u.Id == currentUserId);
    if (currentUser == null)
    {
        return NotFound();
    }

    // 将用户添加到项目的用户集合中
    project.users = new List<AppUser> { currentUser };
    _unitOfWork.Project.Add(project);
    _unitOfWork.Save();

    return RedirectToAction(nameof(Index), new { id = currentUserId });
}

3. 更安全的用户ID获取方式(避免URL传递)

强烈建议不要通过URL参数传递用户ID,因为用户可以轻松篡改URL中的id值,导致越权访问风险。更安全的方式是直接从当前登录用户的Claims身份中获取ID,完全不需要在URL中暴露:

第一步:修改锚点标签,去掉asp-route-id参数

<a class="nav-link text-dark" asp-area="" asp-controller="Project" asp-action="Index">Projects</a>

第二步:修改控制器方法,直接获取当前用户ID

[Authorize]
public IActionResult Index()
{
    // 直接从当前登录用户身份中获取ID
    var currentUserId = _userManager.GetUserId(User);

    var userProjects = _unitOfWork.Project
        .GetAll(includeProperties: "users")
        .Where(p => p.users.Any(u => u.Id == currentUserId))
        .ToList();

    return View(userProjects);
}

第三步:修改创建项目的POST方法,同样直接获取当前用户ID

[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Project project)
{
    if (!ModelState.IsValid)
    {
        return View(project);
    }

    var currentUserId = _userManager.GetUserId(User);
    var currentUser = _unitOfWork.AppUser.Get(u => u.Id == currentUserId);

    project.users = new List<AppUser> { currentUser };
    _unitOfWork.Project.Add(project);
    _unitOfWork.Save();

    return RedirectToAction(nameof(Index));
}

这种方式完全避免了URL传递用户ID的安全隐患,而且代码更简洁——用户只能访问自己的项目,即使手动修改URL也无法获取他人数据。


内容的提问来源于stack exchange,提问作者Mr.Grease

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 18:39:08