ADSI 链接服务器:为什么我可以在 VBA 中查询 AD,但不能作为链接服务器查询?

ADSI 链接服务器:为什么我可以在 VBA 中查询 AD,但不能作为链接服务器查询?

在我阅读并研究了所有的内容之后,这似乎是提出这个问题最合理的地方:

为什么我可以使用 VBA 查询 Active Directory,但不能使用 SQL Management Studio 2012 中的链接服务器查询?

首先,我以前能够做到这一点,但是那是很久以前使用 SQL Server 2005 的时候了。

这是我正在尝试的查询:

SELECT * FROM OpenQuery(
ADSI,
'SELECT displayName, title, department, employeeID, userAccountControl
FROM ''LDAP://dc=testdomain''
WHERE objectCategory = ''Person'' AND
      objectClass = ''user'' AND
      userAccountControl=512')

这是我收到的错误:

Msg 7321, Level 16, State 2, Line 1
An error occured while preparing the query "SELECT displayName, title, department, employeeID, userAccountControl
            FROM 'LDAP://dc=testdomain'
            WHERE objectCategory = 'Person' AND
                  objectClass = 'user' AND
            userAccountControl=512" for execution against OLE DB provider "ADsDSOObject" for linked server "ADSI".

此错误消息的问题在于它非常通用,似乎没有提供任何有用的信息。我读到的所有内容似乎都是权限问题或查询语法,我假设它与我的 SQL 实例登录上下文有关,以及在链接服务器中设置安全性的方式。下面的 VBA 代码可以工作,并且正在使用非常相似的查询,即使是最简单的查询也无法在链接服务器中工作。我还可以访问我尝试链接到的 Active Directory,这可以通过我在底部提供的 VBA 代码片段(仅供参考)证明。问题是,我相信我拥有使其正常工作的所有正确权限。

但是,不同网站上提出的许多建议都涉及对 SQL 实例进行修改,由于此服务器仍在构建中,因此无法轻易看出其长期影响。我拥有临时提升的权限来构建它。

以下是我设置链接服务器的详细信息和参数:

SQL Server 11.0.5058
Linked Server: ADSI
Provider: OLE DB Provider for Microsoft Directory Services
Product name: Active Directory Services 2.5
Data source: adsdatasource
Provider string: ADsDSOObject

Be made using the login's current security context

Ole DB Provider  Options:
Allow in process

但是,我发现唯一可能与所有其他博客中关于此错误的区别是,当我尝试深入到链接服务器表并查看时(服务器对象 > 链接服务器 > ADSI > 目录 > 默认 > 表)。单击展开表级别后,我收到以下错误:

Failed to retreive data for this request. (Microsoft.SqlServer.Management.Sdk.Sfc)

Additional information:
    An exception occured while executing a Transact-SQL statement or batch.
    (Microsoft.SqlServer.ConnectionInfo)
        Cannot obtain the required interface ("IID_IDBSchemaRowset") from OLE DB provider "ADsDSOObject"
        for linked server "ADSI". (Microsoft SQL Server, Error: 7301)

IID_IDBSchemaRowset似乎是我唯一的线索,但它看起来像是一个深而黑暗的兔子洞,不确定那是不是我需要去的地方。 帮助!

以供参考

'References: Microsoft ActiveX Data Objects 2.8 Library
Public Sub testADSI()
    On Error Resume Next

    Dim cn As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim rs as ADODB.Recordset
    Dim MySql as String
    Dim n as Integer

    Set cn = New ADODB.Connection
    Set cmd = New ADODB.Command
    Set rs = New ADODB.Recordset

    cn.Provider = "ADsDSOObject"
    cn.Open "Active Directory Provider"

    Set cmd.ActiveConnection = cn

    cmd.Properties("Page Size")= 1000

    MySql = "SELECT displayName, title, department, employeedID, userAccountControl " & _
            "FROM 'LDAP://dc=testdomain' " _ &
            "WHERE objectCategory = 'Person' AND " & _
                  "objectClass = 'user' AND " & _
                  "userAccountControl=512" 

    rs.Open MySql, cn, 1

    If rs.RecordCount > 0 Then
        MsgBox "Sucess! " & rs.RecordCount & " records found!"
    Else
        MsgBox "No records"
    End IF
End Sub

答案1

如果您在链接服务器的安全设置页面中使用“不使用安全上下文进行”选项,则可能会发生这种情况。这会导致进行匿名 LDAP 调用。目前(Server 2008 或更高版本)默认情况下不允许匿名 LDAP 操作。

我的测试表明,“使用登录的安全上下文进行”选项会在 SQL 服务器服务正在运行的凭据下进行 LDAP 调用。

我可能会建议使用“使用登录的安全上下文进行”,将本地登录映射到远程用户或仅输入默认凭据(对话框中的选项 4):

在此处输入图片描述

在所有情况下,我建议为链接服务器使用专用的 AD 用户帐户。

请注意,您正在查询 userAccountControl 等敏感属性。默认情况下,普通域用户无法读取此属性,即您的查询可能不会返回完整的结果集。您可以使用专用 AD 帐户来解决这个问题,并在适用的情况下授予其对 userAccountControl 属性的读取权限。

另外我建议不要使用无服务器绑定。至少指定域名:

LDAP://mydomain.local/dc=mydomain,dc=local

这可以帮助您避免 LDAP 响应缓慢和/或数据不一致。

相关内容