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

求助:.NET 6 API+Angular内网应用本地AD认证及SQL用户角色配置

实现方案步骤

一、.NET 6 API 配置AD认证

  • 安装必要包:Microsoft.AspNetCore.Authentication.Negotiate,用于处理Windows/AD集成认证
  • 在Program.cs中配置认证与授权服务:
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});
  • 启用认证、授权中间件(放在路由中间件之前):
app.UseAuthentication();
app.UseAuthorization();

配置完成后,API可通过User.Identity.Name获取AD用户名,自动完成身份验证。

二、用户信息同步与存储到MS SQL

  1. 创建用户实体类:
public class AppUser
{
    public int Id { get; set; }
    public string AdUsername { get; set; } // 关联AD用户名
    public string DisplayName { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    // 可扩展其他字段(邮箱、部门等)
}
  1. 用EF Core配置DbContext并映射到SQL:
public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
    public DbSet<AppUser> Users { get; set; }
}
  1. 实现用户同步逻辑(首次访问时自动创建SQL用户记录):
    安装System.DirectoryServices.AccountManagement包用于读取AD用户详情,然后编写中间件:
public class UserSyncMiddleware
{
    private readonly RequestDelegate _next;
    private readonly AppDbContext _dbContext;

    public UserSyncMiddleware(RequestDelegate next, AppDbContext dbContext)
    {
        _next = next;
        _dbContext = dbContext;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        if (context.User.Identity.IsAuthenticated)
        {
            var adUsername = context.User.Identity.Name;
            var existingUser = await _dbContext.Users.FirstOrDefaultAsync(u => u.AdUsername == adUsername);
            
            if (existingUser == null)
            {
                var domainContext = new PrincipalContext(ContextType.Domain);
                var adUser = UserPrincipal.FindByIdentity(domainContext, adUsername);
                
                var newUser = new AppUser
                {
                    AdUsername = adUsername,
                    DisplayName = adUser.DisplayName
                };
                
                _dbContext.Users.Add(newUser);
                await _dbContext.SaveChangesAsync();
            }
        }
        await _next(context);
    }
}

在Program.cs中注册中间件:

app.UseMiddleware<UserSyncMiddleware>();

三、自定义角色与声明的实现

  1. 创建角色、用户角色关联、自定义声明实体:
public class AppRole
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<AppUserRole> UserRoles { get; set; }
}

public class AppUserRole
{
    public int UserId { get; set; }
    public AppUser User { get; set; }
    public int RoleId { get; set; }
    public AppRole Role { get; set; }
}

public class AppUserClaim
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public AppUser User { get; set; }
    public string ClaimType { get; set; }
    public string ClaimValue { get; set; }
}
  1. 在DbContext中配置实体关系,生成迁移并更新SQL数据库。
  2. 实现ClaimsTransformation,将SQL中的角色/声明注入用户身份:
public class CustomClaimsTransformer : IClaimsTransformation
{
    private readonly AppDbContext _dbContext;

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

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        if (!principal.Identity.IsAuthenticated)
            return principal;

        var adUsername = principal.Identity.Name;
        var user = await _dbContext.Users
            .Include(u => u.UserRoles)
                .ThenInclude(ur => ur.Role)
            .Include(u => u.UserClaims)
            .FirstOrDefaultAsync(u => u.AdUsername == adUsername);

        if (user == null)
            return principal;

        var claimsIdentity = (ClaimsIdentity)principal.Identity;

        // 添加角色声明
        foreach (var userRole in user.UserRoles)
        {
            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, userRole.Role.Name));
        }

        // 添加自定义声明
        foreach (var userClaim in user.UserClaims)
        {
            claimsIdentity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
        }

        return principal;
    }
}

在Program.cs中注册该服务:

builder.Services.AddTransient<IClaimsTransformation, CustomClaimsTransformer>();

四、Angular前端配置与权限处理

  1. 配置HTTP拦截器,确保请求携带AD凭据:
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class CredentialsInterceptor implements HttpInterceptor {
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const modifiedRequest = request.clone({
      withCredentials: true
    });
    return next.handle(modifiedRequest);
  }
}

在app.module.ts中注册拦截器:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { CredentialsInterceptor } from './credentials.interceptor';

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: CredentialsInterceptor, multi: true }
  ]
})
export class AppModule { }
  1. 前端权限控制:调用API的/api/user/me端点获取当前用户的角色/声明,根据返回值控制菜单、按钮的显示隐藏,或拦截路由跳转。

五、API权限验证示例

  • 按角色限制接口访问:
[Authorize(Roles = "Admin")]
[HttpGet("admin-dashboard")]
public IActionResult AdminDashboard()
{
    return Ok("管理员专属内容");
}
  • 按自定义声明验证:
[Authorize]
[HttpPost("edit-user")]
public IActionResult EditUser()
{
    if (!User.HasClaim("Permission", "EditUser"))
    {
        return Forbid();
    }
    // 执行编辑逻辑
    return Ok();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 14:35:35