IsUserInRole вызывает GetRolesForUser?

Когда я реализую класс RoleProvider и вызываю Roles.IsUserInRole(строковое имя пользователя, строковое имя_роли), выполнение кода сначала переходит к методу "GetRolesForUser(строковое имя пользователя)". Почему это? Я не хочу повторять все роли, когда я просто ищу единственное значение того, принадлежит ли этот пользователь одной роли. Является ли это ограничением класса поставщика ролей .NET или есть что-то, что я могу сделать, чтобы немного больше контролировать выполнение кода?

Вот код вызова

if (Roles.IsUserInRole(CurrentUser.UserName, "Teacher")) {

А вот реализация IsUserInRole

public override bool IsUserInRole(string username, string roleName) { return true; }

Но код GetRolesForUser всегда реализуется первым:

public override string[] GetRolesForUser(string username) {
        string[] roles = GetAllRoles();
        List<string> userRoles = new List<string>();
        foreach (string role in roles) {
            if (IsUserInRole(username, role)) {
                userRoles.Add(role);
            }
        }
        return userRoles.ToArray();
    }

person Josh    schedule 02.11.2010    source источник
comment
Трудно понять, как это возможно, это абстрактный метод. Опубликуйте свою реализацию.   -  person Hans Passant    schedule 02.11.2010


Ответы (2)


Существует решение уровня поставщика ролей Майкрософт, которое позволяет кэшировать роли пользователя в файле cookie, поэтому ему не нужно вызывать метод GetRolesForUser поставщика. Я считаю, что кеширование файлов cookie является частью класса Roles, поэтому, если вы реализуете его из базового класса RoleProvider, оно должно быть совместимым. Стоит взглянуть на код в рефлекторе, чтобы получить представление о том, как MS реализует свои собственные абстрактные классы и что делают статические вспомогательные классы (роли и членство).

Попробуйте добавить cacheRolesInCookie="true" в элемент roleManager в файле конфигурации и посмотрите, изменится ли поток.

Поскольку вы используете собственную реализацию RoleProvider, вы также можете переопределить метод IsUserInRole и предоставить собственную реализацию проверки того, находится ли пользователь в роли.

ОБНОВЛЕНИЕ: этот блок кода вызывается внутри метода Roles.IsUserInRole:

IPrincipal currentUser = GetCurrentUser();
if (((currentUser != null) && (currentUser is RolePrincipal)) && ((((RolePrincipal) currentUser).ProviderName == Provider.Name) && StringUtil.EqualsIgnoreCase(username, currentUser.Identity.Name)))
{
    flag = currentUser.IsInRole(roleName);
}
else
{
    flag = Provider.IsUserInRole(username, roleName);
}

Блок else — это то, что вызовет метод IsUserInRole вашего пользовательского поставщика.

Таким образом, роли для вашего пользователя еще не добавлены в объект Principal. Если вы просто еще не дошли до этого шага, хорошо. Если нет, обязательно сделайте это. Это гарантирует, что каждый раз, когда вы вызываете Roles.IsUserInRole или User.IsInRole, эти функции будут использовать кэш ролей пользователя в памяти (после загрузки) вместо того, чтобы каждый раз обращаться к базе данных. (Хотя поставщик базовых ролей и класс диспетчера ролей должны позаботиться об этом за вас.)

Можете ли вы проверить параметры файла конфигурации для поставщика ролей? Кроме того, какую версию .net вы используете? Вы вручную управляете процессом входа в систему или используете элемент управления входом в систему .net? Вы внедрили собственный класс ролей? Или вы используете System.Web.Security.Roles?

person ulty4life    schedule 02.11.2010
comment
Попытался добавить cacheRolesInCookie=true в поставщика ролей, но GetRolesForUser по-прежнему вызывается. - person Josh; 03.11.2010
comment
Вы нашли исправление для этого? Если я передам две случайные строки, они перейдут к InUserInRole, но если я передам свой активный каталог в параметре имени пользователя, он заставит его получить GetRolesForUser!! - person Murphybro2; 23.08.2017

RoleProvider.IsUserInRole(имя пользователя, пароль) используется для проверки ролей для данного пользователя, который не является текущим пользователем входа в систему (для текущего пользователя входа в систему вместо этого также используется Principal.IsInRole). А для RolePrincipal он всегда использует GetRolesForUser для кэширования ролей и выполняет проверку ролей среди кэшированного списка ролей. (источник)

может пользователь Roles.Provider.IsUserInRole вместо Roles.IsUserInRole

person user553838    schedule 07.12.2011