【问题标题】:Storing and retrieving Active Directory objectGUID in SQL Server在 SQL Server 中存储和检索 Active Directory objectGUID
【发布时间】:2014-11-24 21:51:27
【问题描述】:

我即将完成这项工作。我需要在我们的 Intranet 上识别用户。我需要将该用户的objectGUID 存储在 SQL Server 数据库表中,并且能够再次检索该记录。我有几个不同的应用程序,PHP、ASP Classic 和 ASP.Net。我认为在 SQL Server 中执行 AD 查找可能是最简单的。

我可以使用本教程http://sql.dzone.com/news/querying-active-directory-thro中的步骤连接到 AD

我可以检索objectGUID 和我需要的任何其他内容,但我不确定如何将objectGUID 存储在数据库中或如何使用objectGUID 查询数据库。

我认为它是数据类型(128 长度字节数组?),需要转换,但我不知道该怎么做。

从活动目录中选择一条记录并插入到表中会显示插入的数据类型 objectGUID 为 varbinary(256)

select  *
into temp_table
from  openquery(adsi, '
select  givenName,
                sn,
                sAMAccountName,
                objectGUID              
from    ''LDAP://dc=somedomain,dc=com''
where   sAMAccountName = ''some_user''
')

为了测试,我尝试使用从上面的 temp_table 检索到的 objectGUID 查询 AD。

declare @qry varchar(8000)
declare @var varbinary(256)
set @var = (SELECT objectGUID from temp_table)
set @qry = 'select *
from openquery(ADSI, ''
    select
    givenName, 
    sn, 
    sAMAccountName
    from ''''LDAP://DC=somedomain,DC=com'''' 
    where objectGUID = ''''+@var+''''   
    ORDER BY displayName
'')'

exec(@qry)

不返回任何行...

最初我认为这是带引号的正确语法

where objectGUID = '+@var+'

但返回错误:数据类型的运算符无效。运算符等于add,类型等于varchar

所以也许我的语法错误,或者仍然是数据类型问题?

提前致谢。

【问题讨论】:

    标签: sql-server active-directory


    【解决方案1】:

    要在单个查询中从 AD 中检索数据,当您要求特定对象 GUID 或多个 GUID 时,有一种方法可以使用 where 子句而不是 from LDAP://<GUID=your guid> 表达式(这在查询的情况下非常方便单个 GUID)。

    查询的 where 子句中 Active Directory 对象的 GUID 必须是字符串形式,其中 GUID 以十六进制表示法表示的每个字节前面都有反斜杠符号:

    \1B\C1\93\F8\25\32\72\4E\8B\48\48\62\BB\44\49\7A
    

    例如,您有 GUID:F893C11B-3225-4E72-8B48-4862BB44497A。首先,您必须将其转换为 binary(16) 类型(长度为 16 的字节数组),然后转换为十六进制字符串,最后插入反斜杠,如上例所示:

    declare @g uniqueidentifier = 'F893C11B-3225-4E72-8B48-4862BB44497A';
    declare @gs nvarchar(max);
    
    set @gs = CONVERT(nvarchar(max), CONVERT(binary(16), @g), 2);
    
    declare @c int = 16;
    while @c > 0
    begin
    set @c = @c - 1;
    set @gs = STUFF(@gs, (2 * @c) + 1, 0, '\');
    end;
    
    declare @q nvarchar(max) = 
    'select * from openquery(AD, 
    '' select cn from ''''LDAP://DC=domain,DC=com'''' 
    where objectGUID = ''''' + @gs + '''''  
    '')';
    
    exec(@q);
    

    以上代码创建以下查询:

    select * from openquery(AD, 'select cn from ''LDAP://DC=domain,DC=com'' where objectGUID = ''\1B\C1\93\F8\25\32\72\4E\8B\48\48\62\BB\44\49\7A'' ')
    

    【讨论】:

      【解决方案2】:

      您是否在 TSQL 中尝试过 CASTCONVERThttp://msdn.microsoft.com/en-us/library/ms187942.aspx 有几个例子。

      【讨论】:

        【解决方案3】:

        不清楚您所说的“如何使用objectGUID查询数据库”是什么意思,但是如果您想知道确切的数据类型,有两种方法:

        1. 如果您至少使用 SQL Server 2012,那么您可以尝试sp_describe_first_result_set。它有几个限制,因此并非在所有情况下都有效。

        2. 您可以将结果转储到临时表中,然后检查其结构:

          SELECT fields
          INTO #tmp
          FROM openquery(...);
          
          EXEC tempdb.dbo.sp_help '#tmp';
          

        在创建列来存储值或声明局部变量时,使用返回的任何数据类型(可能是BINARY(128)VARBINARY(128))。

        编辑:
        所以我们现在知道objectGUID 是一个VARBINARY(256)。为了在查询中正确使用它,请从已转义字符串中的转义字符串中删除三组单引号。此外,我们需要将 VARBINARY 转换为 VARCHAR,以便可以将其连接到动态 SQL 字符串中。使用CONVERT 函数时,请务必使用1 的“样式”编号,它将十六进制数字转换为十六进制数字字符串(即“0x12D5”);如果您未指定“样式”,则默认操作是转换为这些十六进制数字表示的字符(即“Hello!”)。

        DECLARE @Query VARCHAR(8000),
                @ObjectGUID VARBINARY(256);
        
        SELECT @ObjectGUID = objectGUID
        FROM   temp_table;
        
        SET @Query = 'SELECT *
        FROM OPENQUERY(ADSI, ''
            SELECT
            givenName, 
            sn, 
            sAMAccountName
            FROM ''''LDAP://DC=somedomain,DC=com'''' 
            WHERE objectGUID = ' + CONVERT(VARCHAR(300), @ObjectGUID, 1) + '
            ORDER BY displayName;
         '')';
        
        PRINT @Query; -- see what SQL is being executed
        EXEC(@Query);
        

        【讨论】:

        • @user1633947 包含变量时引号过多。值本身不会被引用。您有 4 个单引号,可以转换为 2 个单引号,但它已经在一个字符串中,因此等同于字符串中的转义引号。意思是,您没有包含@var 的值,而是说WHERE objectGUID = '+@var+' 正在寻找“+@var+”的字符串文字。我已经用更正的语法更新了我的答案。
        【解决方案4】:

        我还在我的项目中将 AD 中的 objectGUID 存储到 SQL 服务器中,并且我使用 uniqueidentifier。 (但是我不使用 OpenQuery,而是使用 Windows 服务不断从 AD 同步并填充数据库。)

        虽然从 AD 获取 objectGUID 时显示为二进制数组 (varbinary),
        它实际上是表示一个GUID,SQL中对应的类型是uniqueidentifier。
        GUID 的大小仅为 16 字节(128 位)。

        这未经测试,但请尝试以下方法:

        Select CONVERT(uniqueIdentifier,objectGUID) as Id, ...
        FROM OpenQuery(ADSI,
            'SELECT objectGUID, ...
             FROM ...
             WHERE...')
        

        【讨论】:

        • 好吧,既然你提到它,这听起来很可悲;-)。它一定是太累了,并且没有在名称的“GUID”部分上找到它(是的,我同意了)。如果可行,我会 +1。
        【解决方案5】:

        我无法在 where 子句中使用 objectGUID,但我确实发现我可以直接绑定到 objectGUID,这给了我相同的最终结果。

        DECLARE @qry varchar(8000) 
        DECLARE @ObjectGUID uniqueIdentifier
        
        SET @ObjectGUID = (SELECT objectGUID FROM temp_table)
        
        SET @qry = 'select *
        FROM openquery(ADSI, ''
            SELECT  givenName,
                        sn,
                        sAMAccountName,
                        objectGUID              
        from    ''''LDAP://<GUID=' + CAST(@ObjectGUID as CHAR(36)) + '>''''
        '')'
        
        EXEC(@qry)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-09
          • 1970-01-01
          • 1970-01-01
          • 2023-04-06
          相关资源
          最近更新 更多