从网络外的本地计算机中确定用户Active Directory组

本文关键字:用户 Active Directory 计算机 网络 | 更新日期: 2023-09-27 18:22:34

我当前的项目要求我根据Active Directory组验证用户。问题是,计算机可能并不总是连接到域,但用户可能仍然需要运行该工具。我知道在未连接时无法查询Active Directory,而是尝试查询机器SAM(MSAM)。

断开网络连接时,我在确定当前用户时遇到问题。以下是我正在使用的:

PrincipalContext principalctx = new PrincipalContext(ContextType.Machine);
UserPrincipal uprincipal = new UserPrincipal(principalctx);

从这一点来看,我该如何询问当前登录到本地机器的用户。

当连接到域时,我可以使用UserPrincipal.Current进行查询。如果我没有连接到域,它将失败,说"The server could not be contacted"。注意:使用上面的代码无法使用此方法,相反,我可以放弃PrincipalContext,直接查询当前用户。识别当前用户后,我可以查询GetGroups()并确定他们是否在所需的组中。

另外,有人能描述一下ContextType的三个选项ApplicationDirectory, Domain, Machine吗。恐怕我没有完全理解每个选项,因此可能使用错误。

从网络外的本地计算机中确定用户Active Directory组

从顶部开始:

我当前的项目要求我根据Active验证用户目录组。问题是,电脑可能并不总是已连接到域,但用户可能仍需要运行该工具。

因此,在这一点上,您必须接受攻击者能够绕过任何强制的安全性,因为它完全是在客户端上强制的。不完全是解决方案的一部分,但请记住。

我知道我不能查询Active Directory已连接,但我正在尝试查询机器SAM(MSAM)。

安全帐户管理器仅存储本地帐户(MACHINENAME''Administrator和其他帐户)。它将没有域用户凭据。您想到的是LSA缓存,它会记住最后N个域登录的凭据(其中N是组策略配置的从0到50的数字)和最后N个SID到名称的映射(默认为128,可通过注册表配置)。安全帐户管理器仅将域帐户存储在域控制器上。

我在确定当前用户时遇到问题断开与网络的连接。以下是我使用的内容:PrincipalContextprincipalctx=新的PrincipalContext(ContextType.Machine);UserPrincipal upincipal=新的UserPrincipar(principalctx);

另外,有人能描述一下三个ContextType选项吗ApplicationDirectory,域,计算机。恐怕我没有完全理解理解每个选项,因此可能使用错误。

如上所述,信息不被缓存,但ContextType枚举可以描述如下:

来自MSDN:

  • 域:域存储。这表示AD DS存储(正如它所说,这是针对域帐户的,就像在Active Directory的LDAP目录访问中一样,这需要网络访问)
  • ApplicationDirectory:应用程序目录存储。这表示AD LDS存储(AD轻型目录服务(以前称为ADAM)是Active Directory的一个较小版本,旨在存储单个应用程序的凭据。它与本讨论无关,但也使用LDAP。)
  • 机器:计算机商店。这代表SAM存储(仅枚举本地帐户)

从这一点来看,我该如何询问谁当前登录到本地机器

您总是可以通过调用WindowsIdentity.GetCurrent()来检查登录的用户。如果登录是在脱机状态下进行的,这将返回已登录用户的SID和组SID(可能已缓存)。

当连接到域时,我可以使用UserPrincipal.Current进行查询。如果我没有连接到域,它将失败,并显示"服务器无法联系"。注意:使用在上面的代码中,我可以放弃PrincipalContext,直接查询当前用户。识别当前用户后,我可以查询GetGroups(),并确定它们是否在所需的组中。

要确定组成员身份,请检查所需的组SID是否在WindowsIdentity.GetCurrent返回的标识中。如果您没有在访问控制系统中使用SID,您可以通过调用SecurityIdentifier.translate将名称转换为SID。您需要在联机时进行转换,然后缓存以供脱机使用。它既可以存储为字符串,也可以存储为二进制,因此两者都可以很好地放在注册表中。

// while we are online, translate the Group to SID
// Obviously, administrators would be a bad example as it is a well known SID...
var admins = new NTAccount("Administrators");
var adminSid = (SecurityIdentifier)admins.Translate(typeof(SecurityIdentifier));
// store the sid as a byte array on disk somewhere 
byte[] adminSIDbytes = new byte[adminSid.BinaryLength];
adminSid.GetBinaryForm(adminSIDbytes, 0);
// at time of check, retrieve the sid and check membership
var sidToCheck = new SecurityIdentifier(adminSIDbytes, 0);
if (!wi.Groups.Contains(sidToCheck))
    throw new UnauthorizedAccessException("User is not a member of required group");

另一种情况:

  • 如果您想使用PrincipalContext获取网络域名,请确保您验证了身份验证和授权。如下所示:获取网络域名