求助:.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
- 创建用户实体类:
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; // 可扩展其他字段(邮箱、部门等) }
- 用EF Core配置DbContext并映射到SQL:
public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<AppUser> Users { get; set; } }
- 实现用户同步逻辑(首次访问时自动创建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>();
三、自定义角色与声明的实现
- 创建角色、用户角色关联、自定义声明实体:
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; } }
- 在DbContext中配置实体关系,生成迁移并更新SQL数据库。
- 实现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前端配置与权限处理
- 配置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 { }
- 前端权限控制:调用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
相关产品推荐
相关产品推荐

