2009-12-18 10 views
9

Estoy usando WindowsTokenRoleProvide para determinar la membresía de un grupo de Active Directory en una aplicación web de ASP.NET.Rendimiento insuficiente con WindowsTokenRoleProvider

Mi problema es que el rendimiento no es bueno, especialmente cuando un usuario está en muchos grupos. Como ejemplo, estoy en grupos de 253 (!), Y WindowsTokenRoleProvider demora alrededor de 150 segundos para determinar en qué grupos estoy.

Sé que puedo usar el almacenamiento en caché para que esto no se haga en solicitudes posteriores de un usuario, pero obviamente no es aceptable tomar tanto tiempo en el primer golpe.

¿Cuáles son mis opciones? ¿Puedo forzar WindowsTokenRoleProvider para considerar solo ciertos grupos? (Solo estoy interesado en 5).

Respuesta

12

Algunas pruebas han revelado que mi problema es que llamar:

Roles.IsUserInRole(groupName) 

está accediendo al método GetRolesForUser en el RoleProvider - que está recuperando detalles de cada función el usuario es un miembro de.

Pero llamar:.

Roles.Provider.IsUserInRole(groupName) 

determina si el usuario está en el grupo - sin recuperar los detalles de cada función el usuario está en

extraño, pero parece que el uso de Roles.Provider.IsUserInRole se resolver mi problema

* ACTUALIZACIÓN *

Resulta que esto es sólo una solución parcial; si uso comprobaciones de permisos imperativas, o 'Permitir' y 'negar' en web.comfig, entonces WindowsTokenRoleProvider todavía va y lentamente Obtiene los detalles de cada grupo el usuario es miembro de: o (

Así que mi pregunta sigue se encuentra ...

* ACTUALIZACIÓN *

he resuelto mediante la creación de una clase que se extiende desde WindowsTokenRoleProvider y primordial GetRolesForUser por lo que sólo comprueba la pertenencia de los roles especificados en la configuración de almacenamiento en caché Incluye también:.

/// <summary> 
/// Retrieve the list of roles (Windows Groups) that a user is a member of 
/// </summary> 
/// <remarks> 
/// Note that we are checking only against each system role because calling: 
/// base.GetRolesForUser(username); 
/// Is _very_ slow if the user is in a lot of AD groups 
/// </remarks> 
/// <param name="username">The user to check membership for</param> 
/// <returns>String array containing the names of the roles the user is a member of</returns> 
public override string[] GetRolesForUser(string username) 
{ 
    // Will contain the list of roles that the user is a member of 
    List<string> roles = null; 

    // Create unique cache key for the user 
    string key = String.Concat(username, ":", base.ApplicationName); 

    // Get cache for current session 
    Cache cache = HttpContext.Current.Cache; 

    // Obtain cached roles for the user 
    if (cache[key] != null) 
    { 
     roles = new List<string>(cache[key] as string[]); 
    } 

    // Was the list of roles for the user in the cache? 
    if (roles == null) 
    { 
     roles = new List<string>(); 

     // For each system role, determine if the user is a member of that role 
     foreach (SystemRoleElement role in WebConfigSection.Settings.SystemRoles) 
     { 
      if (base.IsUserInRole(username, role.Name)) 
      { 
       roles.Add(role.Name); 
      } 
     } 

     // Cache the roles for 1 hour 
     cache.Insert(key, roles.ToArray(), null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration); 
    } 

    // Return list of roles for the user 
    return roles.ToArray(); 
} 
+0

Gracias, Cocowalla. Exactamente lo que vine buscando. –

+0

En realidad estoy en el bote similar. Entonces, ¿soluciona el problema de la conexión por primera vez también? ¿Tomará más tiempo para que el usuario se conecte por primera vez y luego más rápido? –

+0

Tardará un poco más la primera vez, pero nada que el usuario note (porque usamos 'IsUserInRole' para verificar solo la membresía de grupos en los que realmente estamos interesados) – Cocowalla

Cuestiones relacionadas