Действительно медленный WindowsTokenRoleProvider

В приложении MVC5 я использую проверку подлинности Windows и хотел использовать наши группы Active Directory в качестве ролей, так как это строго приложение для внутренней сети. Я использую WindowsTokenRoleProvider так:

<roleManager defaultProvider="WindowsProvider" enabled="true" cacheRolesInCookie="false">
  <providers>
    <add name="WindowsProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
  </providers>
</roleManager>

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

User.IsInRole(@"Domain\UserName")

Я что-то упустил при настройке? Я не могу поверить, что для проверки подлинности было бы нормально занять 20 секунд. Пользователь, которого я проверяю, состоит из ~50 групп, но я не думал, что этого будет достаточно, чтобы сильно его замедлить.

1 ответ

Решение

Таким образом, лучшим решением на данный момент является вопрос стека

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

ОБНОВЛЕНИЕ: Так, фактически перечисляя мои группы, я обнаружил, что мой пользователь был в более чем 400 группах, что может объяснить, почему это заняло так много времени. Я до сих пор не понимаю, почему метод IsInRole для пользователя будет вызывать GetRolesForUser вместо того, чтобы просто вызывать IsUserInRole напрямую, но это делает экспоненциально быстрее

ОБНОВЛЕНИЕ 2: Старый ответ был удален, так вот мой класс:


    public class CustomWindowsTokenRoleProvider : WindowsTokenRoleProvider
    {
        public override string[] GetRolesForUser(string username)
        {
            List roles = null;
            string key = String.Concat(username, ":", base.ApplicationName);
            Cache cache = HttpContext.Current.Cache;

            if (cache[key] != null)
            {
                roles = new List(cache[key] as string[]);
            }

            if (roles == null)
            {
                roles = new List();

                // AppSettings.APPLICATION_GROUPS is an IEnumerable that returns just the groups that my application is interested in checking against
                foreach (string role in AppSettings.APPLICATION_GROUPS)
                {
                    if (base.IsUserInRole(username, role));
                    {
                        roles.Add(role);
                    }
                }

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

            return roles.ToArray();
        }
    }
Другие вопросы по тегам