You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

ASP.NET Core 2.0 MVC内网系统:AD用户角色检索与Identity类集成咨询

嘿,我来帮你搞定这个问题!你已经有AD认证的基础,现在需要把自定义数据库里的角色整合到ASP.NET Core的认证系统里,这样就能用[Authorize(Roles="Admin")](你之前写的Authenticate是笔误,正确特性是Authorize)来做权限控制了。下面是具体的步骤和代码实现:

实现思路

核心逻辑是:AD认证通过后,从你的MSSQL数据库中查询当前用户的角色,将角色添加到用户的Claims集合中,这样ASP.NET Core的授权系统就能识别这些角色并生效。我们可以通过IClaimsTransformation接口来实现这个角色注入的过程。


1. 确保数据库上下文与实体类配置正确

首先要保证你的数据库上下文和实体类能正确映射到Users、Roles、UserRoles表,示例如下:

// 实体类
public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string UserNameAd { get; set; } // 存储AD用户名(需与AD中的用户名完全匹配)
    public ICollection<UserRole> UserRoles { get; set; }
}

public class Role
{
    public int Id { get; set; }
    public string RoleName { get; set; }
    public ICollection<UserRole> UserRoles { get; set; }
}

public class UserRole
{
    public int User_Id { get; set; }
    public int Role_Id { get; set; }
    public User User { get; set; }
    public Role Role { get; set; }
}

// 数据库上下文
public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<UserRole> UserRoles { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 配置UserRoles的复合主键
        modelBuilder.Entity<UserRole>()
            .HasKey(ur => new { ur.User_Id, ur.Role_Id });
    }
}

2. 实现自定义Claims转换类

创建一个类实现IClaimsTransformation接口,这个类会在用户认证通过后自动执行,负责从数据库加载角色并添加到Claims中:

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;

public class CustomClaimsTransformer : IClaimsTransformation
{
    private readonly AppDbContext _dbContext;

    public CustomClaimsTransformer(AppDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var identity = principal.Identity as ClaimsIdentity;
        // 如果用户未认证,直接返回原对象
        if (identity == null || !identity.IsAuthenticated)
        {
            return principal;
        }

        // 获取AD用户名(格式通常是DOMAIN\UserName,需和数据库中UserNameAd的存储格式一致)
        string adUserName = identity.Name;

        // 从数据库查询用户及关联的角色
        var user = await _dbContext.Users
            .Include(u => u.UserRoles)
            .ThenInclude(ur => ur.Role)
            .FirstOrDefaultAsync(u => u.UserNameAd == adUserName);

        if (user != null && user.UserRoles.Any())
        {
            // 将每个角色添加为ClaimTypes.Role类型的Claim
            foreach (var userRole in user.UserRoles)
            {
                identity.AddClaim(new Claim(ClaimTypes.Role, userRole.Role.RoleName));
            }
        }

        return new ClaimsPrincipal(identity);
    }
}

3. 在Startup.cs中配置认证、授权与Claims转换

ConfigureServices方法中注册相关服务,确保AD认证、数据库上下文和自定义Claims转换类被正确注入:

public void ConfigureServices(IServiceCollection services)
{
    // 注册数据库上下文
    services.AddDbContext<AppDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    // 配置Windows AD认证(内网系统常用)
    services.AddAuthentication(IISDefaults.AuthenticationScheme);

    // 注册自定义Claims转换服务
    services.AddScoped<IClaimsTransformation, CustomClaimsTransformer>();

    // 启用授权服务
    services.AddAuthorization();

    // 注册MVC服务
    services.AddMvc();
}

Configure方法中启用认证和授权中间件(注意顺序:认证在前,授权在后):

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    // 启用认证中间件
    app.UseAuthentication();
    // 启用授权中间件
    app.UseAuthorization();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

4. 使用授权特性

现在你可以在控制器或Action上直接使用[Authorize(Roles="Admin")]特性来控制访问权限了:

[Authorize(Roles = "Admin")]
public class AdminController : Controller
{
    public IActionResult Dashboard()
    {
        return View();
    }
}

注意事项

  • 用户名匹配:确保数据库中UserNameAd字段的值和AD返回的用户名(identity.Name)格式完全一致,比如是否包含域名前缀(如DOMAIN\ZhangSan)。
  • 性能优化:如果角色数据不频繁变动,可以考虑添加缓存(比如用IMemoryCache),避免每次请求都查询数据库。
  • 权限验证:如果需要更复杂的权限逻辑,可以扩展AuthorizationHandler实现自定义授权策略。

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

火山引擎 最新活动