2009-12-18 6 views
9

J'utilise WindowsTokenRoleProvide r pour déterminer l'appartenance à un groupe Active Directory dans une application Web ASP.NET.Mauvaise performance avec WindowsTokenRoleProvider

Mon problème est que les performances ne sont pas bonnes, surtout quand un utilisateur est dans plusieurs groupes. Par exemple, je suis dans 253 (!) Groupes, et WindowsTokenRoleProvider prend environ 150 secondes pour déterminer dans quels groupes je suis.

Je sais que je peux utiliser la mise en cache afin que cela ne soit pas fait sur les demandes suivantes pour un utilisateur, mais évidemment, il n'est pas acceptable de prendre autant de temps sur le premier coup.

Quelles sont mes options? Puis-je forcer WindowsTokenRoleProvider à ne considérer que certains groupes? (Je suis seulement intéressé par 5).

Répondre

12

Des tests ont révélé que mon problème est que l'appel:

Roles.IsUserInRole(groupName) 

accède à la méthode GetRolesForUser dans la RoleProvider - qui est en train de récupérer les détails de chaque rôle l'utilisateur est membre.

Mais appeler.

Roles.Provider.IsUserInRole(groupName) 

détermine si oui ou non l'utilisateur est dans le groupe - sans récupérer les détails de chaque rôle que l'utilisateur se trouve dans

Bizarre, mais il ressemble à l'aide Roles.Provider.IsUserInRole sera résoudre mon problème.

* MISE À JOUR *

Il se trouve que cela est juste une solution partielle; si j'utilise des contrôles d'autorisation impératif, ou « autorise » et «deny dans web.comfig, puis WindowsTokenRoleProvider va encore et lentement obtient les détails de chaque groupe auquel l'utilisateur est membre de: o (

Alors ma question encore se tient ...

* MISE à JOUR *

Je résolu ce problème en créant une classe qui étend de WindowsTokenRoleProvider et dominante GetRolesForUser donc il ne vérifie les membres des rôles spécifiés dans la configuration il comprend aussi la mise en cache.

/// <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

Merci, Cocowalla. Exactement ce que je suis venu chercher. –

+0

Je suis actuellement dans le même bateau. Est-ce que cela résout aussi le problème de la première connexion? L'utilisateur aura-t-il besoin de plus de temps pour se connecter la première fois et ensuite plus rapidement? –

+0

Cela prendra un peu plus de temps la première fois, mais rien que l'utilisateur remarquera (parce que nous utilisons 'IsUserInRole' pour vérifier uniquement l'appartenance aux groupes qui nous intéressent réellement) – Cocowalla

Questions connexes