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

ASP.NET Core中基于用户的访问控制方案求助

适配方案推荐:EF Core全局查询筛选器 + SQL Server行级安全(RLS)

你的场景属于基于资源所有者的细粒度访问控制,RBAC/PBAC更适合粗粒度的角色/权限划分,无法直接满足“仅允许资源所有者修改自己数据”的需求,而以下两个微软官方方案的组合完全适配你的要求,且均经过严格测试、能获得持续安全更新:

一、EF Core 全局查询筛选器(自动拦截应用层操作)

这是EF Core原生特性,能自动为所有查询、更新、删除操作添加筛选条件,确保用户仅能访问/修改自己创建的书籍,无需在每个Action中手动编写检查逻辑。

实现步骤:

  1. 扩展Book实体:添加CreatedByUserId字段,用于存储书籍创建者的用户ID:
public class Book
{
    public int BookId { get; set; }
    public string Title { get; set; }
    public int CreatedByUserId { get; set; } // 新增字段
}
  1. 在DbContext中配置全局筛选器:
    通过注入IHttpContextAccessor获取当前登录用户ID,为Book实体添加全局筛选规则:
public class AppDbContext : DbContext
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public AppDbContext(DbContextOptions<AppDbContext> options, IHttpContextAccessor httpContextAccessor)
        : base(options)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public DbSet<Book> Books { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 获取当前登录用户ID
        var userIdClaim = _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);
        if (int.TryParse(userIdClaim, out var currentUserId))
        {
            // 为Book实体添加全局查询筛选器
            modelBuilder.Entity<Book>()
                .HasQueryFilter(book => book.CreatedByUserId == currentUserId);
        }
    }
}
  1. 自动应用筛选逻辑:
    配置完成后,EF Core会自动将筛选条件应用到所有针对Book的查询、Update、Delete操作。例如恶意用户B尝试修改用户A的书籍时,EF Core会自动附加CreatedByUserId = B的ID的条件,因查询不到匹配数据,更新操作会被静默拦截(或返回0行受影响)。

二、SQL Server 行级安全(RLS):数据库层面的兜底防护

作为应用层筛选的补充,RLS能在数据库层面拦截绕过EF Core的直接SQL操作(如恶意用户直接执行UPDATE语句),进一步提升安全性。

实现步骤:

  1. 创建安全函数:用于获取当前会话的用户ID(需与应用层传递的用户ID一致):
CREATE FUNCTION dbo.GetCurrentUserId()
RETURNS INT
WITH SCHEMABINDING
AS
BEGIN
    RETURN CAST(SESSION_CONTEXT(N'UserId') AS INT);
END;
GO
  1. 启用行级安全并创建访问策略:
-- 为Books表启用行级安全
ALTER TABLE dbo.Books ENABLE ROW LEVEL SECURITY;
GO

-- 创建策略:仅允许用户访问自己创建的书籍
CREATE POLICY Books_UserAccessPolicy
ON dbo.Books
FOR ALL -- 对SELECT/INSERT/UPDATE/DELETE均生效
USING (CreatedByUserId = dbo.GetCurrentUserId());
GO
  1. 在EF Core中传递用户ID到数据库会话:
    在DbContext的SaveChangesAsync方法中,将当前用户ID写入SQL Server的会话上下文:
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
    var userIdClaim = _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);
    if (!string.IsNullOrEmpty(userIdClaim))
    {
        // 将用户ID写入SQL Server会话上下文
        await Database.ExecuteSqlRawAsync(
            $"EXEC sp_set_session_context @key=N'UserId', @value={userIdClaim}", 
            cancellationToken);
    }
    return await base.SaveChangesAsync(cancellationToken);
}

方案优势

  • 无需手动检查:全局筛选器自动覆盖所有EF Core操作,避免重复代码和人为疏漏。
  • 官方支持:两个特性均为微软官方产品的原生功能,与EF Core 7完全兼容,可获得持续的安全更新和技术支持。
  • 多层防护:应用层+数据库层的双重拦截,全面覆盖可能的攻击路径。

内容的提问来源于stack exchange,提问作者Bluebaron

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:52:07