Вопрос
Как я могу достоверно сказать, представляет ли данная строка NTAccount
или SecurityIdentifier
?
Подробно
Учитывая строку, которую я могу преобразовать это к NTAccount
или SecurityIdentifier
через конструктор:
[string]$myAccount = '...' # some value
$ntAccount = [System.Security.Principal.NTAccount]::new($myAccount)
$sid = [System.Security.Principal.SecurityPrincipal]::new($myAccount) // throws exception if not a valid SID
Если строка не является SID, конструктор SecurityIdentifier выдаст исключение. Если строка является SID, конструктор NTAccount примет ее ... однако, когда я попытаюсь преобразовать ее в SID, будет выдано исключение System.Security.Principal.IdentityNotMapped
.
$sidFromNT = $ntAccount.Translate([System.Security.Principal.SecurityPrincipal]) # throw exception
$ntFromSid = $sid.Translate([System.Security.Principal.NTAccount]) # should work as if the SID were invalid we'd have already erred
Было бы здорово, если Я мог бы сказать, что не знаю тип, используя общий базовый класс; но это абстрактно / не имеет конструктора publi c; поэтому я не могу сделать это:
[string]$account = '...'
$idRef = [System.Security.Principal.IdentityReference]::new($account) # this is not valid code
$ntFromId = $idRef.Translate([System.Security.Principal.NTAccount])
$sidFromId = $idRef.Translate([System.Security.Principal.SecurityIdentifier])
Таким образом, единственные варианты, о которых я могу думать, это варианты:
- Используйте ошибку * для определения типа; но это делает ошибку частью моего обычного потока.
- Проверьте, начинается ли значение
S-
; очень быстрый и должен работать в большинстве случаев; но это взлом.
* Примечание: я понимаю, что недопустимое значение (то есть ни учетная запись NT, ни SID) также не исключаются; Я проигнорировал этот сценарий, чтобы оставаться кратким.
-
C# Версия
Так как это вопрос. net, а не спецификация PowerShell c, вот код, иллюстрирующий ту же проблему в C# (к сожалению, я не могу изменить это, поскольку различные сайты Fiddle ограничивают требуемую функциональность).
public static void Main()
{
var ids = new string[] {"S-1-1-0", "Everyone"}; // a list of values which may be SIDs or NTAccounts
var pseudoRandomIndex = DateTime.Now.Millisecond % ids.Length; // saves initialising Random for a simple demo
var idString = ids[pseudoRandomIndex]; // pick one id at random; be it a SID or an NT Account
Debug.WriteLine($"Selected value is {idString}");
TryToProcessIdentityReference<NTAccount, SecurityIdentifier>(idString, (id) => new NTAccount(id));
TryToProcessIdentityReference<SecurityIdentifier, NTAccount>(idString, (id) => new SecurityIdentifier(id));
}
static void TryToProcessIdentityReference<T1, T2>(string idString, Func<string, T1> callConstructor)
where T1 : IdentityReference
where T2 : IdentityReference
{
var t1Type = typeof(T1);
var t2Type = typeof(T2);
Console.WriteLine($"Trying to process {idString} as a {t1Type.Name} ...");
try
{
var t1 = callConstructor(idString);
_ = t1.Translate(t2Type);
Debug.WriteLine($" - {idString} is a valid {t1Type.Name}!");
} catch (Exception e) when(e is ArgumentException || e is IdentityNotMappedException) {
Debug.WriteLine($" - Failed to process {idString} as {t1Type.Name}; error thrown when translating to {t2Type.Name}");
Debug.WriteLine($" - {e.ToString()}");
}
}