我的应用程序中已经有了LDAP身份验证。我如何去获取字段,如'给定名称'或'姓氏'从LDAP存储和存储在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'DOMAINlogin',
@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地址(可以在命令提示符ipconfig在"连接特定的dns后缀"下找到)是corp.domain.net那么它是 " LDAP://DC=corp,DC=domain,DC=net " 或者只是domain.net是 " LDAP://DC=domain,DC=net "
查找要选择的字段
如果您要在上面的select语句中使用全列操作符(*),您将获得objectClass的User的所有可能字段,您可以对Groups执行相同的操作,以便发现您需要返回哪些字段,字段名称区分大小写。
objectSid是我怀疑你想要的字段,这可以存储在SQL Server作为varbinary(256)。
过滤LDAP数据
您还可以通过使用userAccountControl字段(值列表)来检查帐户的状态,这是一个位字段,您可以在OPENQUERY函数中使用LDAP_MATCHING_RULE_BIT_OR进行位检查,该函数为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中没有禁用该帐户,该语句将返回用户' nuptime '的详细信息。
插入,更新(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中删除历史用户时不会失去它们。
希望对你有帮助。
我知道这被标记为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"