我被指派修改WinForms应用程序,基本上检查登录用户是否属于特定域。 这是我到目前为止所提出的:
byte[] domainSid;
var directoryContext =
new DirectoryContext(DirectoryContextType.Domain, "domain.se");
using (var domain = Domain.GetDomain(directoryContext))
using (var directoryEntry = domain.GetDirectoryEntry())
domainSid = (byte[])directoryEntry.Properties["objectSid"].Value;
var sid = new SecurityIdentifier(domainSid, 0);
bool validUser = UserPrincipal.Current.Sid.IsEqualDomainSid(sid);
有更好/更简单的方法吗? 对我来说,似乎可以使用PrincipalContext或System.Security.Principal中的其他类以某种方式访问domainSid。
我考虑使用硬编码的SID字符串,但我不知道它是多么“正确”。
答案 0 :(得分:4)
你正在做的事情对我来说是最好的选择。硬编码字符串定义并不是一个好主意。
答案 1 :(得分:3)
每个域都有一个内置帐户 domainName \ administrator ,因此您可以创建一个具有此名称的帐户,将其转换为SecurityIdentifier并阅读AccountDomainSid属性。
这种方式的一个例子是:
public static class SecurityEx
{
public static SecurityIdentifier DomainSId
{
get
{
var administratorAcount = new NTAccount(GetDomainName(), "administrator");
var administratorSId = (SecurityIdentifier) administratorAcount.Translate(typeof (SecurityIdentifier));
return administratorSId.AccountDomainSid;
}
}
internal static string GetDomainName()
{
//could be other way to get the domain name through Environment.UserDomainName etc...
return IPGlobalProperties.GetIPGlobalProperties().DomainName;
}
}
您还可以找到其他解决方案,通过WMI或Lsa获得相同的结果。这对我来说似乎是最优雅的方式。
答案 2 :(得分:0)
以下是接受答案的略有不同的方法:
using System.Security.Principal;
using System.DirectoryServices;
//...
void Main()
{
var sidHelp = new SecurityIdentifierHelper();
Console.WriteLine(sidHelp.GetDomainSecurityIdentifier("MyDomain"));
}
//...
public class SecurityIdentifierHelper
{
const int OffsetBinaryFormStartingIndex = 0; // just to avoid magic numbers; though this is still a bit magic. Documentation says "The byte offset to use as the starting index in binaryForm", whatever that means.
// https://referencesource.microsoft.com/#mscorlib/system/security/principal/sid.cs,d06a8d5ee0c7a26d,references
// https://docs.microsoft.com/en-us/dotnet/api/system.security.principal.securityidentifier.-ctor?view=netframework-4.8#System_Security_Principal_SecurityIdentifier__ctor_System_Byte___System_Int32_
public SecurityIdentifier GetDomainSecurityIdentifier(string domain)
{
var ldapPath = $"LDAP://{domain}";
var domainAdsi = new DirectoryEntry(ldapPath);
var domainSidByteArray = (byte[])domainAdsi.Properties["objectSid"].Value;
return new SecurityIdentifier(domainSidByteArray, OffsetBinaryFormStartingIndex);
}
}
Console.WriteLine(new System.Security.Principal.SecurityIdentifier(((byte[])new System.DirectoryServices.DirectoryEntry("LDAP://MyDomain").Properties["objectSid"].Value), 0));
[string]$myDomain = 'MyDomain' # or 'MyDomain.example.com'
[string]$ldapPath = 'LDAP://{0}' -f $MyDomain
[adsi]$domainAdsi = [adsi]$ldapPath
[System.Security.Principal.SecurityIdentifier]::new($domainAdsi.Value, 0)
[System.Security.Principal.SecurityIdentifier]::new(([ADSI]('LDAP://MyDomain')).Value, 0)
答案 3 :(得分:0)
要获取域的sid,只需执行以下简单查询即可:
public static SecurityIdentifier GetDomainSid(string domainName)
{
byte[] domainSidBytes = ((byte[])new System.DirectoryServices.DirectoryEntry($"LDAP://{ domainName }").Properties["objectSid"].Value);
SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(domainSidBytes, 0);
return sid;
}
警告:当域名无法解析或用户无权查询活动目录时,此方法将引发异常。