我的应用程序中有 LDAP 身份验证。如何从 LDAP 存储中获取“givenname”或“surname”等字段并将它们存储在 SQL 数据库中?
此外,是否也可以仅在 LDAP 'uid' 与存储在本地数据库中的 'uid' 匹配时授权用户?
任何帮助,将不胜感激。谢谢。
可以使用 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'
然后,您可以使用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 语句必须是连续的一行,没有换行符,否则会抛出错误。
如果您的域 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 中。
您还可以使用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”的详细信息。
当我使用 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 中删除,您就不会丢失历史用户。
希望有帮助。
我知道这被标记为 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"