Роль провайдер кеширует по запросу?

Мое приложение MVC использует Роль пользователя в нескольких местах во время запросов отдельных страниц. Мой вопрос заключается в том, кэширует ли SqlRoleProvider по умолчанию кэширование текущих ролей пользователя в течение срока действия запроса страницы?

Например, я использую роли в атрибутах методов Controller:

[Authorize(Roles = "Admin")]

и пользовательский код

if (user.IsInRole(MembershipRole.Admin))
{
     // Do something
}
else if (user.IsInRole(MembershipRole.Printer))
{
     // Do something else
}

Если поставщик ролей не кэширует роли, является ли лучшим решением написать собственный поставщик ролей, который наследует от стандартного, и переопределить методы, чтобы получить роли один раз и кэшировать их на время запроса? Можно ли это сделать так, чтобы и атрибут Authorize, и мой собственный код использовали кэшированные роли?

(Если вам интересно, я не хочу использовать параметр cacheRolesInCookie web.config для кэширования ролей в файлах cookie).

Спасибо заранее за любые предложения.

[Изменить, чтобы включить детали, полученные из ответа Джо]

Я декомпилировал System.Web.Mvc.AuthorizeAttribute, и метод AuthorizeCore вызывает следующий метод для каждой проверяемой роли:

httpContext.User.IsInRole

Затем вглядываясь в System.Web.Security.RolePrincipal (что и означает "пользователь" выше), оба метода, приведенные ниже, действительно используют кэшированную копию ролей пользователя (или заполняют кэш, если он пуст):

public string[] GetRoles()
public bool IsInRole(string role)

Кэш хранится как поле для пользователя, поэтому его время жизни соответствует продолжительности запроса.

Методы находят роли, используя:

Roles.Providers[this._ProviderName].GetRolesForUser(this.Identity.Name)

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

1 ответ

Решение

Если вы используете RoleProvider в приложении ASP.NET или ASP.NET MVC, затем HttpContext.User будет ссылаться на RolePrincipal который выполняет кеширование ролей в течение всего срока действия запроса.

Однако в службе WCF, которая использует роли ASP.NET:

<behavior ...>
    <serviceAuthorization principalPermissionMode ="UseAspNetRoles"
                     roleProviderName ="MyRoleProvider" />
</behavior>

это не так: вместо этого HttpContext.User будет ссылаться на внутренний класс System.ServiceModel.Security.RoleProviderPrincipal, который не кэширует роли: вместо этого он всегда вызывает RoleProvider.IsUserInRole,

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

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

Не обязательно для ASP.NET или ASP.NET MVC, но может быть предусмотрено для WCF. Кэширование на длительность запроса предположительно будет использовать HttpContext.Items, поэтому введем зависимость от существования HttpContext, но это не обязательно проблема, за исключением усложнения юнит-тестирования.

Можно ли это сделать так, чтобы и атрибут Authorize, и мой собственный код использовали кэшированные роли?

Если вы настраиваете свой кастом RoleProvider в web.config больше ничего не нужно делать, чтобы Authorize Атрибут будет использовать его.

Другие вопросы по тегам