IsUserInRole вызывает GetRolesForUser?

Когда я реализую класс RoleProvider и вызываю Roles.IsUserInRole(имя пользователя строки, string roleName), выполнение кода сначала переходит к методу 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();
    }

Ответ 1

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

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

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

UPDATE: Этот блок кода вызывается внутри метода 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?

Ответ 2

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

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