在我的公司,我们有一个自定义HMI。如果用户愿意,该HMI可以使用计算机的域登录。这是我们目前正在尝试解决的问题
当用户以域用户身份登录Windows时,他们使用相同的Windows凭据登录HMI - 一切顺利。
网络连接断开,用户重新启动计算机。
用户可以像以前一样使用相同的域登录登录Windows(使用Windows缓存用户允许此操作)
用户尝试登录我们的HMI,他们不能,因为我还没有想出如何访问这些缓存的活动目录用户。
这是我正在使用的代码,用于检测用户是否是允许登录HMI的组之一。这些组存储在我们的SQL数据库中,并存储为SERVER\BUILDER
等字符串,例如
If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
WinPrincipal = New WindowsPrincipal(tempWindowsIdentity)
End If
If WinPrincipal.IsInRole(user.Group) Then
'Success - obviously there's more code after this
End If
问题是,当用户未连接到域时,我会在IsInRole
方法上获得异常。我看了一下方法中的重载,并尝试使用user.Group的SID等效而不是文字String。这似乎有效,但现在又出现了另一个问题。当用户不在网络上时,我无法将组名(SQL中的字符串)转换为这些SID。
我目前的解决方法是,当用户连接到域时,我将SID和组保存到查找表(加密)中,然后当网络未连接时,我从数据库中获取组名称并按字面意思查找表中的SID字符串。
我用来将组名转换为SID的代码如下
'' Get all groups available to the user
For i As Integer = 0 To WindowsIdentity.GetCurrent.Groups.Count - 1
Dim ir As IdentityReference = WindowsIdentity.GetCurrent.Groups(i)
sid(i) = New SecurityIdentifier(ir.Value)
sidName(i) = CType(ir.Translate(GetType(NTAccount)), NTAccount).Value
' Write to file as csv
writer.WriteLine(sidName(i) + "," + sid(i).ToString)
Next
然后我像这样查找组名
If File.Exists(FILEPATH) = True Then
Dim reader As New StreamReader(FILEPATH)
While Not reader.EndOfStream
Dim sTemp() As String = reader.ReadLine.Split(",")
If groupName.Equals(sTemp(0)) Then
Return New SecurityIdentifier(sTemp(1))
End If
End While
End If
我不能在不在网络上时将组名转换为SID的原因是IdentityReference.Translate
因为无法看到域而引发异常。
所以,经过所有这些解释后,这就是我正在寻找的东西。我想在某个地方必须有访问才能从组名中获取SID,因为Windows必须将其存储在某个地方,否则我将无法在未连接到网络时登录到Windows。
我做了很多搜索,但我无法弄清楚这些缓存凭据的存储位置。任何帮助将不胜感激,如果我不够清楚,请告诉我,我会尽力解释。
答案 0 :(得分:0)
我知道它已经老了,但这对我来说很实际。 作为一个熟悉的帖子,我将链接这个:Determine User Active Directory Groups from Local Machine off Network
建议的解决方案是将SID存储在本地空间中,这似乎是最好的主意。