Una entrada rápida, no como la de ayer. Aunque el tema está bastante relacionado ya que ambos tratan de Active Directory e identidades.
Hoy vamos a ver una forma sencilla de obtener todos los grupos a los que pertenece un usuario, y agruparlos por su nombre de dominio. Y todo esto mediante una sola sentencia LINQ to objects. A ver quién es el guapo o guapa que me dice que LINQ to objects no es una maravilla!
El resultado que vamos a obtener es el siguiente (algunos nombres se han omitido por razones obvias :-P):
Groups under:
- Group name: Todos
- Group name: LOCAL
Groups under: BUILTIN
- Group name: Usuarios
- Group name: Administradores
Groups under: PRIMARY_DOMAIN_NAME
- Group name: xxx1
- Group name: xxx2
- Group name: xxx3
- Group name: xxx4
- Group name: xxxN
Groups under: NT AUTHORITY
- Group name: INTERACTIVE
- Group name: Usuarios autentificados
Y el código resultante es un método extensor para la clase WindowsIdentity, con dos funciones auxiliares en forma de métodos extensores de la clase NTAccount:
using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
namespace Alpha.Code
{
public static class SecurityExtensions
{
public static IOrderedEnumerable<IGrouping <string, NTAccount>>
GetGroupsUnderDomains(this WindowsIdentity identity)
{
var groups =
from grIdentity in identity.Groups
where grIdentity.IsValidTargetType(typeof(NTAccount))
select grIdentity.Translate(typeof(NTAccount)) as NTAccount into ntAccounts
let domainName = ntAccounts.GetDomainName()
let groupName = ntAccounts.GetAccountName()
orderby domainName
group ntAccounts by domainName into domainGroups
orderby domainGroups.Key
select domainGroups;
return groups;
}
public static string GetDomainName(this NTAccount account)
{
string[] split = account.Value.Split('\\');
return split.Length == 1 ? string.Empty : split[0];
}
public static string GetAccountName(this NTAccount account)
{
string[] split = account.Value.Split('\\');
return split[split.Length - 1];
}
}
}
Para probarlo y ver el resultado:
var groups = WindowsIdentity.GetCurrent().GetGroupsUnderDomains();
foreach (var dg in groups)
{
Console.WriteLine(string.Format("Groups under: {0}", dg.Key));
foreach (var g in dg)
{
Console.WriteLine(string.Format(" - Group name: {0}", g.GetAccountName()));
}
}
Un saludo desde las frías tierras de Andorra :-)
Noviembre 2009
** crossposting desde el blog de Lluís Franco en geeks.ms **
Posted
Thu, Nov 26 2009 11:53
by
lfranco