.Net 6中Visus.LdapAuthentication如何配置多SearchBase做LDAP认证
解决Visus.LdapAuthentication多域LDAP认证问题
核心思路
由于你的两个SearchBase属于不同的LDAP域(DC=EEEEEEE,DC=com和DC=FFFFFFF,DC=com),无法通过单配置实现跨域搜索,最可靠的方式是分别注册两组独立的LDAP服务,再通过自定义门面服务统一处理认证和搜索逻辑。
步骤1:配置文件中添加两组LDAP配置
在appsettings.json中新增两个独立的LDAP配置节点,分别对应两个域:
{ "LdapConfiguration1": { "Server": "ldap.eeeeeee.com", "Port": 389, "SearchBase": "OU=01-EEEEEEE,OU=Utilisateurs,DC=EEEEEEE,DC=com", "BindDn": "你的绑定账号DN", "BindPassword": "绑定账号密码", "SearchFilter": "(sAMAccountName={0})" }, "LdapConfiguration2": { "Server": "ldap.fffffff.com", "Port": 389, "SearchBase": "OU=02-FFFFFFF,OU=Utilisateurs,DC=FFFFFFF,DC=com", "BindDn": "你的绑定账号DN", "BindPassword": "绑定账号密码", "SearchFilter": "(sAMAccountName={0})" } }
步骤2:注册两组命名LDAP服务
在Program.cs中,分别注册两组LDAP认证和搜索服务,使用命名服务区分不同实例:
// 注册第一组LDAP服务 builder.Services.AddKeyedScoped<ILdapAuthenticationService, LdapAuthenticationService>("ldap-domain1", (sp, key) => { var opt = new LdapAuthenticationOptions(); builder.Configuration.GetSection("LdapConfiguration1").Bind(opt); return new LdapAuthenticationService(opt, sp.GetRequiredService<ILogger<LdapAuthenticationService>>()); }); builder.Services.AddKeyedScoped<ILdapSearchService<LdapUser>, LdapSearchService<LdapUser>>("ldap-domain1", (sp, key) => { var opt = new LdapAuthenticationOptions(); builder.Configuration.GetSection("LdapConfiguration1").Bind(opt); return new LdapSearchService<LdapUser>(opt, sp.GetRequiredService<ILogger<LdapSearchService<LdapUser>>>()); }); // 注册第二组LDAP服务 builder.Services.AddKeyedScoped<ILdapAuthenticationService, LdapAuthenticationService>("ldap-domain2", (sp, key) => { var opt = new LdapAuthenticationOptions(); builder.Configuration.GetSection("LdapConfiguration2").Bind(opt); return new LdapAuthenticationService(opt, sp.GetRequiredService<ILogger<LdapAuthenticationService>>()); }); builder.Services.AddKeyedScoped<ILdapSearchService<LdapUser>, LdapSearchService<LdapUser>>("ldap-domain2", (sp, key) => { var opt = new LdapAuthenticationOptions(); builder.Configuration.GetSection("LdapConfiguration2").Bind(opt); return new LdapSearchService<LdapUser>(opt, sp.GetRequiredService<ILogger<LdapSearchService<LdapUser>>>()); });
步骤3:实现多域认证门面服务
创建一个自定义服务,整合两组LDAP认证逻辑,依次尝试两个域的认证:
public class MultiDomainLdapAuthenticationService : ILdapAuthenticationService { private readonly ILdapAuthenticationService _domain1AuthService; private readonly ILdapAuthenticationService _domain2AuthService; public MultiDomainLdapAuthenticationService( [FromKeyedServices("ldap-domain1")] ILdapAuthenticationService domain1AuthService, [FromKeyedServices("ldap-domain2")] ILdapAuthenticationService domain2AuthService) { _domain1AuthService = domain1AuthService; _domain2AuthService = domain2AuthService; } public async Task<bool> AuthenticateAsync(string username, string password, CancellationToken cancellationToken = default) { // 先尝试第一个域 try { if (await _domain1AuthService.AuthenticateAsync(username, password, cancellationToken)) return true; } catch (Exception) { // 忽略单个域的连接/认证异常,继续尝试第二个域 } // 再尝试第二个域 try { return await _domain2AuthService.AuthenticateAsync(username, password, cancellationToken); } catch (Exception) { return false; } } }
步骤4:实现多域搜索门面服务
同理,创建搜索服务的门面类,整合两个域的用户搜索:
public class MultiDomainLdapSearchService : ILdapSearchService<LdapUser> { private readonly ILdapSearchService<LdapUser> _domain1SearchService; private readonly ILdapSearchService<LdapUser> _domain2SearchService; public MultiDomainLdapSearchService( [FromKeyedServices("ldap-domain1")] ILdapSearchService<LdapUser> domain1SearchService, [FromKeyedServices("ldap-domain2")] ILdapSearchService<LdapUser> domain2SearchService) { _domain1SearchService = domain1SearchService; _domain2SearchService = domain2SearchService; } public async Task<LdapUser?> SearchUserAsync(string username, CancellationToken cancellationToken = default) { var user = await _domain1SearchService.SearchUserAsync(username, cancellationToken); if (user != null) return user; return await _domain2SearchService.SearchUserAsync(username, cancellationToken); } // 若接口有其他方法,按相同逻辑实现即可 }
步骤5:注册门面服务
最后将自定义的门面服务注册到DI容器,覆盖原始接口的默认实现:
builder.Services.AddScoped<ILdapAuthenticationService, MultiDomainLdapAuthenticationService>(); builder.Services.AddScoped<ILdapSearchService<LdapUser>, MultiDomainLdapSearchService>();
替代方案(仅适用于域间有信任关系)
如果两个域之间已建立信任,且绑定账号拥有全局搜索权限,可以尝试使用全局编录(端口3268)进行跨域搜索:
- 将LDAP服务器地址改为全局编录地址,端口设为3268
- SearchBase设为空字符串或根域(如
DC=com) - 修改SearchFilter为包含两个OU的OR条件:
(&(objectClass=user)(|(distinguishedName=*,OU=01-EEEEEEE,OU=Utilisateurs,DC=EEEEEEE,DC=com)(distinguishedName=*,OU=02-FFFFFFF,OU=Utilisateurs,DC=FFFFFFF,DC=com)))
但此方案依赖域信任和高权限账号,稳定性不如独立配置方案。
内容的提问来源于stack exchange,提问作者Kamil
相关产品推荐
相关产品推荐

