检查两个 NTAccount 对象的相等性
Checking the equality of two NTAccount objects
我正在尝试检查服务是否具有对特定本地目录的访问权限:
public static bool HasDirectoryPermissions(String path, FileSystemRights rights, String serviceName)
{
try
{
var directoryAccessControl = Directory.GetAccessControl(path);
ManagementObjectSearcher query = new ManagementObjectSearcher("SELECT * FROM Win32_Service where Name='" + serviceName + "'");
var queryResults = (from ManagementObject x in query.Get() select x);
if (queryResults.Count() > 0)
{
var serviceUser = (string)queryResults.FirstOrDefault().Properties["StartName"].Value;
var serviceUserAccount = new NTAccount(serviceUser);
var rules = directoryAccessControl.GetAccessRules(true, true, typeof(NTAccount));
foreach (var rule in rules)
{
if (rule.GetType() == typeof(FileSystemAccessRule))
{
var accessRule = (FileSystemAccessRule)rule;
if (accessRule.IdentityReference == serviceUserAccount && (accessRule.FileSystemRights & rights) == rights && accessRule.AccessControlType == AccessControlType.Allow)
{
Console.WriteLine("The {0} service has permissions to {1}.", serviceName, path);
return true;
}
}
}
Console.WriteLine("The {0} service does not have directory permissions for {1}.", serviceName, path);
return false;
}
else
{
Console.WriteLine("Could not get directory permissions for {0} because the {1} service is not installed.", path, serviceName);
return false;
}
}
catch (Exception exception)
{
Console.WriteLine("Directory permissions could not be obtained for the {0} service against {1}. {2}", serviceName, path, exception.ToString());
return false;
}
}
但是,问题是 accessRule.IdentityReference == serviceUserAccount
永远不会是真的,因为一方面,我有一个名为 NT AUTHORITY\NETWORK SERVICE
的 NTAccount 类型的 IdentityReference,而我计算的 serviceUserAccount
对象是 NT AUTHORITY\NetworkService
。虽然这两个是同一个账号,但是相等性测试失败,因为这些字符串不完全匹配。你如何正确地测试两个 NTAccount 对象是否相同,尽管它们的语法略有不同?
我刚刚尝试过的一个解决方案是将每个帐户转换为各自的 SecurityIdentifier,然后进行比较:
accessRule.IdentityReference.Translate(typeof(SecurityIdentifier)) == serviceUserAccount.Translate(typeof(SecurityIdentifier))
PS:并非所有 IdentityReference 对象都可以转换为 SID,因此请务必将其包装在 try-catch 块中。
我正在尝试检查服务是否具有对特定本地目录的访问权限:
public static bool HasDirectoryPermissions(String path, FileSystemRights rights, String serviceName)
{
try
{
var directoryAccessControl = Directory.GetAccessControl(path);
ManagementObjectSearcher query = new ManagementObjectSearcher("SELECT * FROM Win32_Service where Name='" + serviceName + "'");
var queryResults = (from ManagementObject x in query.Get() select x);
if (queryResults.Count() > 0)
{
var serviceUser = (string)queryResults.FirstOrDefault().Properties["StartName"].Value;
var serviceUserAccount = new NTAccount(serviceUser);
var rules = directoryAccessControl.GetAccessRules(true, true, typeof(NTAccount));
foreach (var rule in rules)
{
if (rule.GetType() == typeof(FileSystemAccessRule))
{
var accessRule = (FileSystemAccessRule)rule;
if (accessRule.IdentityReference == serviceUserAccount && (accessRule.FileSystemRights & rights) == rights && accessRule.AccessControlType == AccessControlType.Allow)
{
Console.WriteLine("The {0} service has permissions to {1}.", serviceName, path);
return true;
}
}
}
Console.WriteLine("The {0} service does not have directory permissions for {1}.", serviceName, path);
return false;
}
else
{
Console.WriteLine("Could not get directory permissions for {0} because the {1} service is not installed.", path, serviceName);
return false;
}
}
catch (Exception exception)
{
Console.WriteLine("Directory permissions could not be obtained for the {0} service against {1}. {2}", serviceName, path, exception.ToString());
return false;
}
}
但是,问题是 accessRule.IdentityReference == serviceUserAccount
永远不会是真的,因为一方面,我有一个名为 NT AUTHORITY\NETWORK SERVICE
的 NTAccount 类型的 IdentityReference,而我计算的 serviceUserAccount
对象是 NT AUTHORITY\NetworkService
。虽然这两个是同一个账号,但是相等性测试失败,因为这些字符串不完全匹配。你如何正确地测试两个 NTAccount 对象是否相同,尽管它们的语法略有不同?
我刚刚尝试过的一个解决方案是将每个帐户转换为各自的 SecurityIdentifier,然后进行比较:
accessRule.IdentityReference.Translate(typeof(SecurityIdentifier)) == serviceUserAccount.Translate(typeof(SecurityIdentifier))
PS:并非所有 IdentityReference 对象都可以转换为 SID,因此请务必将其包装在 try-catch 块中。