基于ADFS、OpenIDConnect与MVC.net的多AD用户登录域信息查询
获取ADFS认证用户的登录来源域信息(多AD场景)
针对你用OpenID Connect + ASP.NET MVC结合ADFS实现三个AD的用户认证,需要获取用户登录来源域的需求,我分享几个实际项目中用过的可行方案:
方案1:从ADFS默认返回的Claims中提取
ADFS在认证成功后,默认会返回包含用户域信息的声明,最常用的是http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname,它的格式通常是域名\用户名,我们可以直接拆分这个值拿到域名。
代码示例(MVC Controller中)
public IActionResult Index() { // 获取Windows账号名Claim var windowsAccountClaim = User.Claims.FirstOrDefault(c => c.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"); if (windowsAccountClaim != null && !string.IsNullOrEmpty(windowsAccountClaim.Value)) { // 拆分出域名部分 var domainName = windowsAccountClaim.Value.Split('\\')[0]; // 这里可以把domainName存起来或者用于业务逻辑 ViewBag.UserDomain = domainName; } return View(); }
注意:要确保OpenID Connect配置中没有过滤这个Claim,在Startup.cs的认证配置里加上options.ClaimActions.MapAll(),或者单独映射这个Claim:
services.AddOpenIdConnect(options => { // 其他配置(Authority、ClientId等)... // 映射所有Claim,避免默认过滤 options.ClaimActions.MapAll(); });
方案2:在ADFS中配置自定义Claim规则
如果默认的Claim不够用,或者你想直接拿到更清晰的域信息,可以在ADFS服务器上添加自定义声明规则,让它直接返回用户的域信息作为独立Claim。
配置步骤:
- 打开ADFS管理控制台,找到你的应用程序信任
- 进入「颁发转换规则」标签,点击「添加规则」
- 选择「发送LDAP属性作为声明」,点击下一步
- 在「属性存储」中选择目标AD,然后在「LDAP属性」里选「域名」(或
userPrincipalName这类包含域信息的属性),映射到自定义Claim类型(比如custom:userdomain) - 保存规则
在MVC中读取自定义Claim
var domainClaim = User.Claims.FirstOrDefault(c => c.Type == "custom:userdomain"); if (domainClaim != null) { var domainName = domainClaim.Value; // 后续业务处理 }
方案3:通过LDAP查询AD获取域信息
如果上面两种方案都无法实现,你可以在MVC应用中通过LDAP直接查询三个AD服务器,找到用户所属的域。这种方式需要应用程序有访问AD的权限,且效率稍低,建议配合缓存使用。
代码示例
private string GetUserDomainFromAd(string samAccountName) { // 三个AD的LDAP路径 var adLdapPaths = new List<string> { "LDAP://domain1.yourcompany.com", "LDAP://domain2.yourcompany.com", "LDAP://domain3.yourcompany.com" }; foreach (var ldapPath in adLdapPaths) { try { using (var directoryEntry = new DirectoryEntry(ldapPath)) { using (var directorySearcher = new DirectorySearcher(directoryEntry)) { // 根据用户名查询用户 directorySearcher.Filter = $"(&(objectClass=user)(sAMAccountName={samAccountName}))"; directorySearcher.PropertiesToLoad.Add("distinguishedName"); var searchResult = directorySearcher.FindOne(); if (searchResult != null) { // 从LDAP路径中提取域名,也可从distinguishedName解析 var domain = new Uri(ldapPath).Host; return domain; } } } } catch (Exception ex) { // 当前AD无法访问或未找到用户,继续尝试下一个 continue; } } return null; // 三个AD都没找到用户 }
调用时,你可以从Claim中拿到sAMAccountName对应的用户名,传入方法即可查询到所属域。
内容的提问来源于stack exchange,提问作者Swapper
相关产品推荐
相关产品推荐

