从本地计算机关闭网络确定用户Active Directory组

时间:2013-07-16 21:14:51

标签: c# .net authentication active-directory

我当前的项目要求我针对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。我担心我不完全理解每个选项,因此可能使用不正确。

2 个答案:

答案 0 :(得分:8)

从顶部开始:

  

我当前的项目要求我针对Active验证用户   目录组。问题是,计算机可能并非总是如此   已连接到域,但用户可能仍需要运行该工具。

此时,您必须接受攻击者可以绕过任何强制安全性,因为它在客户端上完全强制执行。不完全是解决方案的一部分,但要记住它。

  

据我所知,我不能查询Active Directory   连接,而不是我试图查询机器SAM(MSAM)。

Security Accounts Manager仅存储本地帐户(MACHINENAME \ Administrator和其他帐户)。它不具有域用户凭据。您正在考虑LSA cache,它会记住最后N个域登录的凭据(其中N是组策略配置的0到50之间的数字)和最后一个N SID来命名映射(默认为128,{{ 3}})。安全帐户管理器仅在域控制器上存储域帐户。

  

我在确定当前用户时遇到问题   与网络断开连接。这是我正在使用的:PrincipalContext   principalctx = new PrincipalContext(ContextType.Machine);   UserPrincipal uprincipal = new UserPrincipal(principalctx);

     

此外,有人可以描述三个ContextType选项   ApplicationDirectory,Domain,Machine。我担心我不完全   了解每个选项,因此可能使用不正确。

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

来自MSDN:

  • 域名:域名商店。这代表AD DS存储。 (正如它所说,这适用于域帐户,如在Active Directory的LDAP目录访问中 - 这需要网络访问)
  • ApplicationDirectory:应用程序目录存储。这代表AD LDS商店。 configurable via registry(以前称为ADAM)是Active Directory的较小版本,旨在存储单个应用程序的凭据。它与此讨论无关,但也使用LDAP。) < / LI>
  • 计算机:计算机商店。这代表SAM商店。 (仅枚举本地帐户)
  

从这一点开始,我如何询问当前谁登录到本地   机。

您始终可以致电AD Lightweight Directory Services来检查登录用户。如果在离线时发生登录,这将返回登录用户的SID和组SID,可能已缓存。

  

连接到域后,我可以使用UserPrincipal.Current进行查询。   如果我没有连接到域,它将无法说“服务器   无法联系“。注意:此方法无法使用   上面的代码,我可以直接放弃PrincipalContext   查询当前用户。用当前用户识别我可以查询   GetGroups()并确定它们是否属于所需的组之一。

要确定组成员身份,请检查所需的组的SID是否在WindowsIdentity.GetCurrent返回的标识中。如果您未在Access Control系统中使用SID,则可以通过调用WindowsIdentity.GetCurrent()将名称转换为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");

答案 1 :(得分:0)

另一个案例:

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