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

.NET 7 RESTful API通过依赖注入操作Active Directory数据的方法

.NET 7 连接 Active Directory 实现增改操作的方案

所需NuGet包

不用依赖EF Core(AD并非关系型数据库),核心使用以下两个包:

  • System.DirectoryServices:原生AD操作核心库,支持查询、新增、修改全量操作
  • System.DirectoryServices.AccountManagement(可选):封装了用户、组等常见AD对象的操作逻辑,可简化代码

步骤实现

1. 配置AD连接参数

在appsettings.json中添加AD连接配置:

"ActiveDirectorySettings": {
  "Domain": "your-domain.com",
  "Username": "ad-admin-account",
  "Password": "admin-password",
  "Container": "OU=Users,DC=your-domain,DC=com" // 可选,指定默认操作的组织单元
}

2. 创建AD操作服务类

先定义接口解耦,方便依赖注入:

public interface IActiveDirectoryService
{
    // 新增AD用户
    Task CreateUserAsync(string username, string password, Dictionary<string, object> properties);
    // 更新用户属性
    Task UpdateUserPropertiesAsync(string username, Dictionary<string, object> properties);
}

再实现接口,用DirectoryEntry和DirectorySearcher完成AD操作:

public class ActiveDirectoryService : IActiveDirectoryService
{
    private readonly string _domain;
    private readonly string _username;
    private readonly string _password;
    private readonly string _container;

    public ActiveDirectoryService(IConfiguration configuration)
    {
        var adSettings = configuration.GetSection("ActiveDirectorySettings");
        _domain = adSettings["Domain"];
        _username = adSettings["Username"];
        _password = adSettings["Password"];
        _container = adSettings["Container"] ?? $"DC={_domain.Replace(".", ",DC=")}";
    }

    public async Task CreateUserAsync(string username, string password, Dictionary<string, object> properties)
    {
        using var entry = new DirectoryEntry($"LDAP://{_container}", _username, _password, AuthenticationTypes.Secure);
        using var userEntry = entry.Children.Add($"CN={username}", "user");
        
        // 设置基础必填属性
        userEntry.Properties["samAccountName"].Value = username;
        userEntry.Properties["userPrincipalName"].Value = $"{username}@{_domain}";
        userEntry.Properties["displayName"].Value = properties.TryGetValue("displayName", out var name) ? name : username;
        
        // 批量设置自定义属性
        foreach (var prop in properties)
        {
            if (userEntry.Properties.Contains(prop.Key))
                userEntry.Properties[prop.Key].Value = prop.Value;
        }
        
        // 保存并启用用户
        userEntry.CommitChanges();
        userEntry.Invoke("SetPassword", password);
        userEntry.Properties["userAccountControl"].Value = 512; // 512代表正常启用状态
        userEntry.CommitChanges();
    }

    public async Task UpdateUserPropertiesAsync(string username, Dictionary<string, object> properties)
    {
        using var searcher = new DirectorySearcher(
            new DirectoryEntry($"LDAP://{_domain}", _username, _password, AuthenticationTypes.Secure),
            $"(&(objectClass=user)(samAccountName={username}))",
            properties.Keys.ToArray(),
            SearchScope.Subtree);
        
        var searchResult = searcher.FindOne();
        if (searchResult == null)
            throw new Exception("目标用户不存在");
        
        using var userEntry = searchResult.GetDirectoryEntry();
        foreach (var prop in properties)
        {
            if (userEntry.Properties.Contains(prop.Key))
                userEntry.Properties[prop.Key].Value = prop.Value;
        }
        userEntry.CommitChanges();
    }
}

3. 配置依赖注入

在Program.cs中注册AD服务:

builder.Services.AddScoped<IActiveDirectoryService, ActiveDirectoryService>();

4. 在API控制器中使用

注入服务后直接调用方法完成业务逻辑:

[ApiController]
[Route("api/ad-users")]
public class AdUsersController : ControllerBase
{
    private readonly IActiveDirectoryService _adService;

    public AdUsersController(IActiveDirectoryService adService)
    {
        _adService = adService;
    }

    [HttpPost]
    public async Task<IActionResult> CreateUser([FromBody] AdUserCreateRequest request)
    {
        var properties = new Dictionary<string, object>
        {
            {"displayName", request.DisplayName},
            {"mail", request.Email}
        };
        await _adService.CreateUserAsync(request.Username, request.Password, properties);
        return Ok("用户创建成功");
    }

    [HttpPut("{username}")]
    public async Task<IActionResult> UpdateUser(string username, [FromBody] AdUserUpdateRequest request)
    {
        var properties = new Dictionary<string, object>
        {
            {"displayName", request.DisplayName},
            {"mail", request.Email}
        };
        await _adService.UpdateUserPropertiesAsync(username, properties);
        return Ok("用户属性更新成功");
    }
}

// 请求模型定义
public class AdUserCreateRequest
{
    public string Username { get; set; }
    public string Password { get; set; }
    public string DisplayName { get; set; }
    public string Email { get; set; }
}

public class AdUserUpdateRequest
{
    public string DisplayName { get; set; }
    public string Email { get; set; }
}

注意事项

  • 确保使用的AD账号拥有足够权限(创建/修改用户的权限)
  • 生产环境禁止硬编码密码,建议使用密钥管理工具(如Azure Key Vault)存储敏感信息
  • userAccountControl数值对应不同用户状态:512为正常启用,514为禁用,可按需调整
  • 需添加异常处理逻辑,覆盖网络异常、权限不足、用户重复等场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:57:41