1

我的应用程序中有 LDAP 身份验证。如何从 LDAP 存储中获取“givenname”或“surname”等字段并将它们存储在 SQL 数据库中?

此外,是否也可以仅在 LDAP 'uid' 与存储在本地数据库中的 'uid' 匹配时授权用户?

任何帮助,将不胜感激。谢谢。

4

2 回答 2

1

可以使用 SQL Server 本身,您可以设置链接服务器

注意:您可以通过这种方式返回的默认最大行数为 1000,因此请尽可能限制您的搜索。

添加链接服务器

您可以执行以下 sql 存储过程来添加链接服务器,请务必将第二条语句中的 @rmtuser 和 @rmtpassword 字段替换为有效的登录信息:

EXEC master.dbo.sp_addlinkedserver 
    @server = N'ADSI', 
    @srvproduct=N'Active Directory Services 2.5', 
    @provider=N'ADsDSOObject', 
    @datasrc=N'adsdatasource', 
    @provstr=N'ADSDSOObject'

EXEC master.dbo.sp_addlinkedsrvlogin
    @rmtsrvname=N'ADSI',
    @useself=N'False',
    @locallogin=NULL,
    @rmtuser=N'DOMAIN\login',
    @rmtpassword='password'

选择 LDAP 数据

然后,您可以使用OPENQUERY函数查询 LDAP 示例:

SELECT distinguishedName, sAMAccountName, objectGUID, objectSid, givenName, sn
FROM OPENQUERY(ADSI, 
    'SELECT sn, givenName, objectSid, objectGUID, sAMAccountName, distinguishedName FROM ''LDAP://DC=domain,DC=net'' WHERE objectClass=''User'' AND sAMAccountName = ''nouptime'''
    )
AS derivedtbl_1

注意:OPENQUERY中的 select 语句必须是连续的一行,没有换行符,否则会抛出错误。

LDAP 服务器地址

如果您的域 dns 地址(可以通过命令提示符找到:“连接特定的 DNS 后缀”下的ipconfig )是corp.domain.net ,则构建 ''LDAP://'' 部分,然后它是''LDAP:// DC=corp,DC=domain,DC=net''或者只是domain.net''LDAP://DC=domain,DC=net''

查找要选择的字段

如果您要在上面的 select 语句中使用所有列运算符 (*),您将获得User的objectClass的所有可能字段,您可以对Groups执行相同操作,以发现需要返回的字段,字段名称是大小写敏感的。

objectSid是我怀疑你想要的字段,它可以作为 varbinary(256) 存储在 SQL Server 中。

过滤 LDAP 数据

您还可以使用userAccountControl字段(值列表)检查帐户的状态,这是一个按位字段,您可以使用LDAP_MATCHING_RULE_BIT_OR在OPENQUERY函数中进行按位检查,即1.2.840.113556.1.4.804,示例使用上面的声明:

SELECT distinguishedName, sAMAccountName, objectGUID, objectSid, givenName, sn
FROM OPENQUERY(ADSI, 
    'SELECT sn, givenName, objectSid, objectGUID, sAMAccountName, distinguishedName FROM ''LDAP://DC=domain,DC=net'' WHERE objectClass=''User'' AND sAMAccountName = ''nouptime''' AND (''''userAccountControl:1.2.840.113556.1.4.804:''''<>2)
    )
AS derivedtbl_1

只要该帐户未在 LDAP 中禁用,该语句就会返回用户“nouptime”的详细信息。

插入和更新 (Upserting) LDAP 数据的本地缓存

当我使用 SQL Server 2008R2 时,我可以使用MERGE语句在一个语句中更新此表,例如:

MERGE INTO tblADUsers
    USING (
        SELECT 
            objectSid, 
            LOWER(sAMAccountName) AS sAMAccountName, 
            givenName, 
            sn,
            LOWER(mail) AS mail,
            CURRENT_TIMESTAMP AS DateAdded 
        FROM OPENQUERY(ADSI, 'SELECT mail, sn, givenName, sAMAccountName, objectSid FROM ''LDAP://DC=corp,DC=domain,DC=net'' WHERE objectClass=''User'' AND  (''userAccountControl:1.2.840.113556.1.4.804:''<>2) ')
        AS derivedtbl_1) AS adsoruce
ON tblADUsers.sAMAccountName = adsoruce.sAMAccountName
WHEN MATCHED THEN
    UPDATE SET objectSid= adsoruce.objectSid
        ,givenName = adsoruce.givenName
        ,sn = adsoruce.sn
        ,mail = adsoruce.mail
        ,dtUpdated = getdate()
        ,dtDeleted = NULL
WHEN NOT MATCHED BY SOURCE THEN
    UPDATE SET dtDeleted = getdate()
WHEN NOT MATCHED THEN
    INSERT (objectSid, sAMAccountName, givenName, sn, mail, dtDateAdded)
    VALUES (
            adsoruce.objectSid
            ,adsoruce.sAMAccountName
            ,adsoruce.givenName
            ,adsoruce.sn
            ,adsoruce.mail
            ,adsoruce.DateAdded
            )
OUTPUT deleted.*, $action, inserted.*;

最后的OUTPUT语句向您显示已更新/插入/删除的内容,如果您希望记录正在发生的事情,您可以在之后使用INTO语句将其转储到表中。我还添加了日期字段,以便您可以查看输入、更新或删除用户的时间。我建议不要删除行,而只是将其标记为已删除的日期,这样如果您在用户离开公司后将其从 AD 中删除,您就不会丢失历史用户。

希望有帮助。

于 2013-05-10T17:16:00.073 回答
0

我知道这被标记为 C#,但在 VB 中(如果需要,请使用语言转换器,telerik 非常好)我会做一些事情,例如:

Dim dEntry As New DirectoryServices.DirectoryEntry("LDAPAddress", "USERNAME", "PASSWORD")
Dim dSearcher As New DirectoryServices.DirectorySearcher

'You may need to tweek this next line according to your AD forest'
dSearcher = New DirectoryServices.DirectorySearcher("(&(objectCategory=Person)(objectClass=user))")
dSearcher.SearchRoot = dEntry
dSearcher.SizeLimit = 1000000

Dim srColl As DirectoryServices.SearchResultCollection = dSearcher.FindAll()

For Each result As DirectoryServices.SearchResult In srColl
    Dim resultProperties As DirectoryServices.ResultPropertyCollection = result.Properties

    'Use watch to get the details you need from AD in the resultProperties object'

     'FOR AD GUID'
     Dim ADGuid As String = ""
     If resultProperties.Contains("objectguid") Then
         Dim _byte As Byte() = resultProperties("objectguid").Item(0)
         ADGuid = New Guid(_byte).ToString
     End If

Next

LDAPAddress 看起来像"LDAP://OU=WWWW,OU=XXXX,DC=YYYY,DC=ZZZZ"

于 2013-04-29T14:08:25.810 回答