Низкая производительность с WindowsTokenRoleProvider

Я использую WindowsTokenRoleProvider для определения состава группы Active Directory в веб-приложении ASP.NET.

Моя проблема состоит в том, что производительность не хороша, особенно когда пользователь находится во многих группах. Как пример, я нахожусь в 253(!) группах, и WindowsTokenRoleProvider занимает приблизительно 150 секунд для определения, в каких группах я нахожусь.

Я знаю, что могу использовать кэширование так, чтобы это не было сделано по последующим запросам на пользователя, но очевидно не приемлемо занять у этого много времени на первом хите.

Каковы мои опции? Я могу вызвать WindowsTokenRoleProvider только рассматривать определенные группы? (Я только интересуюсь 5).

9
задан Cocowalla 18 December 2009 в 19:15
поделиться

1 ответ

Некоторое тестирование показало, что моя проблема заключается в том, что вызов:

Roles.IsUserInRole(groupName)

обращается к методу GetRolesForUser в RoleProvider , который извлекает подробные сведения о каждая роль, членом которой является пользователь.

Но вызов:

Roles.Provider.IsUserInRole(groupName)

определяет, находится ли пользователь в группе - без извлечения деталей каждой роли, в которой находится пользователь.

Странно, но похоже использование Roles.Provider.IsUserInRole решит мою проблему.

* UPDATE *

Оказывается, это лишь частичный обходной путь; если я использую императивные проверки разрешений или «разрешить» и «запретить» в web.comfig, тогда WindowsTokenRoleProvider все равно будет работать, а медленно получит подробную информацию о каждой группе, членом которой является пользователь: o (

Так что мой вопрос остается в силе ...

* UPDATE *

Я решил эту проблему, создав класс, расширяющий WindowsTokenRoleProvider, и переопределив GetRolesForUser , чтобы он проверял только принадлежность к ролям, указанным в конфигурации. Он также включает кеширование:

/// <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();
}
12
ответ дан 4 December 2019 в 19:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: