【问题标题】:Ways to fetch domain username from SID string in VBScript从 VBScript 中的 SID 字符串中获取域用户名的方法
【发布时间】:2014-03-13 20:18:11
【问题描述】:

最近我正在使用纯 VBScript 编写系统管理脚本,要求它必须是可移植的,无需额外安装软件。

我有 SID 的字符串版本(例如“S-1-5-21-123456789...”)并且想要获取用户名和域名。

尝试通过 WMI 执行此操作失败的部分原因是它必须在域控制器上搜索 10,000 个对象。

但也许可以通过以下方式之一完成:

  1. via p/invoke from ADVAPI32.DLL's LookupAccountSid function

  2. 如果我们可以假设 .NETfx 2.0 已安装(我真的希望避免,因为它不是完全可移植的)via the System.Security.Principal(C# 中的示例: using System.Security.Principal; string account = new SecurityIdentifier(stringSid).Translate(typeof(NTAccount)).ToString();)

对我有什么建议吗?

【问题讨论】:

    标签: vbscript active-directory


    【解决方案1】:

    在多域林中建立组成员身份。

    Const ADS_SCOPE_ONELEVEL = 1
    Const ADS_SCOPE_SUBTREE = 2
    
    Set objConnection = CreateObject("ADODB.Connection")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    Set objCommand =   CreateObject("ADODB.Command")
    Set objCommand.ActiveConnection = objConnection
    objCommand.Properties("Page Size") = 1000
    Set objRootLDAP = GetObject("LDAP://RootDSE")
    
    objCommand.CommandText = "<LDAP://`your domain A DC full name here`" & ">;(&(objectCategory=group)(name=" & `group name` & ")); samAccountName,distinguishedname,name;subtree"
                   objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
    Set oGroup = objCommand.Execute
    
    DGroupName = oGroup.Fields("distinguishedname")
    Set objGroup = GetObject("LDAP://" & DGroupName)
    
    For Each obj In objGroup.Members
        i = i + 1
    
        If left(obj.cn,9)="S-1-5-21-" Then
            objCommand.CommandText = "<LDAP://`your domain B DC full name here`" & ">;(&(objectCategory=person)(objectSID=" & obj.cn & ")); samAccountName,distinguishedname,name;subtree"
                   objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
            Set exUser = objCommand.Execute
    
            exUserAttribute1 = exUser.Fields("sAMAccountName")
            exUserAttribute2 = exUser.Fields("name")
        Else
            UserAttribute1 = obj.sAMAccountName
            UserAttribute1 = obj.cn
        End if
    

    【讨论】:

      【解决方案2】:

      您可以简单地将 ADSI 绑定到 SID。在 VBScript 中是这样的:

      Dim myUser
      Set myUser = GetObject("LDAP://<SID=S-1-5-21-...>")
      

      【讨论】:

      • 这给出了以下错误(如果给定的 SID 是域或本地):“(null):服务器无法运行。”显然它需要一个目标服务器来查询,但我找不到适用于此的 LDAP DN 字符串。你能详细说明一下吗?
      • 您的建议?像Set myUser = GetObject("LDAP://S-1-5-21-964382842-1330588478-199955091-103152")Set myUser = GetObject("LDAP://&lt;S-1-5-21-964382842-1330588478-199955091-103152&gt;")Set myUser = GetObject("LDAP://&lt;SID=S-1-5-21-964382842-1330588478-199955091-103152&gt;") 这样的任何东西都会出错...
      • 我能想到的唯一另一件事是首先尝试使用rlmueller.net/ByteArrayFunctions.htm 中的 DecSidToHex 函数将其转换为十六进制。
      • 相同的“服务器无法运行”错误...我认为 LDAP 字符串在 URL 的开头需要一个目标服务器或域,这可能会很痛苦,因为我需要查找 SID可以是本地或域。
      【解决方案3】:

      我自己找到的最好的方法是查询 WMI,如下所示:

      Sub GetUserFromSID(BYVAL strSID, BYREF strUserName, BYREF strDomainName)
          'given the SID in string/SDDL form, fetch the user and domain names
          'this method should work for local and parent AD domain users (i.e. direct trust)
          '...but it probably won't work for remote domains over transitive trusts
          On Error Resume Next
          Dim objSID : Set objSID = objWMI.Get("Win32_SID='" & strSID & "'")
          strUserName = objSID.AccountName
          strDomainName = objSID.ReferencedDomainName
          On Error Goto 0
          If strDomainName = "NT AUTHORITY" Then strDomainName = GetHostname() 'so it matches active user queries
      End Sub
      

      如您所见,我必须添加一些错误处理程序——呃,更确切地说——“盲目跳过错误”,因为查询并不总是成功(并且可能有一些潜在的原因不是易于测试)。

      【讨论】:

      • 由于这种方法大部分都有效,因此对于手头的特定任务来说没问题。但我肯定想知道一个更可靠的方法...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-15
      • 2017-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多