使用服务帐户进行活动目录身份验证
本文关键字:活动 身份验证 服务 | 更新日期: 2023-09-27 18:34:55
我正在研究Web Services
,它可以针对Active Directory
对用户进行身份验证。我目前的解决方案正在起作用,但是,我正在尝试采取不同的方法。
我有一个位于防火墙后面的Active Directory
(生产(。我还在DMZ
中安装了Active Directory
.他们之间有一种单向关系。DMZ信任生产,生产不在乎DMZ
。
我试图完成的是 通过DMZ Active Directory
对每个人进行身份验证。目前,根据用户名,我知道要对哪个AD
服务器进行身份验证。
例如,我的生产活动目录(比如说域域.local(和我的DMZ 活动目录(比如说域域域.公共(。在对任何 AD 服务器进行身份验证之前,我会检查其中一个服务器中是否存在提供的用户名。然后,我检查用户是否处于活动状态,然后才进行身份验证。(我在第一个函数中遇到了问题。它永远不会达到第二个或第三个功能(。
更新:添加了所有内容:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.DirectoryServices;
using System.Security.Principal;
using System.DirectoryServices.AccountManagement;
namespace ActiveDirectory
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
public class Service1 : IService1
{
#region Does User Exist in AD
public string local = string.Empty;
public string ldappath = string.Empty;
public string userNameToUse = string.Empty;
public string domain = string.Empty;
public bool DoesUserExist(string userName)
{
string _userName = userName;
bool exist = true;
using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse))
{
if (foundUser == null)
{
exist = false;
}
else
{
return exist;
}
}
}
return exist;
}
#endregion
#region Check if User Active
public bool isActive (string userName)
{
string _userNameToBeSearched = userNameToUse;
string _username = string.Empty;
string _pwd = string.Empty;
if (local == "YES")
{
_username = "xx";
_pwd = "xx";
ldappath = "LDAP://xxx/DC=xx, DC=local";
}
else
{
_username = "xx";
_pwd = "xx";
ldappath = "LDAP://xxx/DC=xx, DC=public";
}
bool isActive = true;
try
{
DirectoryEntry entry = new DirectoryEntry(ldappath, _username, _pwd);
DirectorySearcher search = new DirectorySearcher(entry);
entry.AuthenticationType = AuthenticationTypes.Secure;
search.SearchRoot = entry;
search.Filter = "(SAMAccountName=" + _userNameToBeSearched + ")";
SearchResult results = search.FindOne();
if (results.ToString() != "")
{
int flags = Convert.ToInt32(results.Properties["userAccountControl"][0].ToString());
//CHECK IF THE ACCOUNT IS DISABLED
if (flags == 66050)
{
isActive = false;
}
}
}
catch (DirectoryServicesCOMException ex)
{
ex.ToString();
}
return isActive;
}
#endregion
#region Is user authenticated
public string isAuthenticated (string userName, string pwd)
{
string _userName, _pwd, message;
_userName = userName;
_pwd = pwd;
char[] splitchar = { '@' };
string[] strSplit = _userName.Split(splitchar);
string z = strSplit[0];
if (strSplit.Length == 2)
{
domain = "x.public";
userNameToUse = z.ToString();
local = "NO";
}
else
{
domain = "x.local";
userNameToUse = z.ToString();
local = "YES";
}
if (DoesUserExist (userNameToUse) == true)
{
if (isActive(userNameToUse) == true)
{
try
{
DirectoryEntry entry = new DirectoryEntry(ldappath, userNameToUse, _pwd);
object nativeObject = entry.NativeObject;
var GUIDID = "";
using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
using (var user = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse))
{
if (user != null)
{
GUIDID = user.Guid.ToString();
}
}
message = "Successfully authenticated:" + GUIDID;
}
}
catch (DirectoryServicesCOMException)
{
message = "Invalid password.";
}
}
else
{
message = "Account is disabled";
}
}
else
{
message = "There's an issue with your account.";
}
return message;
}
#endregion
}
}
如果 AD 中存在用户名DMZ
它将返回 true,否则它将返回 false。但是,将有一些用户仅存在于生产 AD 中,但在 DMZ 中没有任何条目。既然,我建立了单向信任,我应该能够做到这一点:
生产和username@domain.public
username@domain.local
但是,即使我指定了完全用户名,如果 DMZ AD 中不存在条目,尽管它在生产 AD 中存在,但它也会返回 null。
关于如何使用具有生产 AD 完全权限的 Web 服务帐户通过DMZ AD
对每个人进行身份验证的任何建议?
请注意,如果需要,我可以提供其余的代码...*
谢谢
域在 PrincipalContext 中的值是什么? 如果尚未使用,则需要为要查找的用户使用正确的域,以使用当前代码。 主体上下文不支持跨林中的域搜索。
下面是一个使用 DirectorySearcher 来执行此操作的示例。
代码有几个问题,我只谈论主要问题。
-
在方法
DoesUserExist
中使用服务帐户(不向PrincipalContext
传递凭据(来查询这两个域。但是在方法isActive
中,对于不同的域,您有不同的凭据。所以我们有 3 个域的 2 个凭据......至少对这两种方法使用一致的方式。
-
对于 1 向信任(例如 A 信任 B(,B 中的帐户应该能够访问域 A 和 B。
也许您可以简单地将受信任域中的帐户用作服务帐户。然后使用服务帐户(用户名和密码为 null(执行所有 AD 访问。因此,您甚至不需要在代码中输入密码。
-
isActive
,"66050"从何而来?
66060 是十六进制中的 10202,表示 (1( 用户、(2( 禁用和 (3( 密码不会过期。要检查帐户是否已启用,请仅选中帐户禁用位 (0x0002(。它应为 0 表示已启用。
-
您已经在
DoesUserExist
中获取了用户主体。可以通过查看UserPrincipal.Enabled
来简单地检查启用。
我需要在日常工作中进行代码审查。现在我也在堆栈溢出上这样做... :)