Роль провайдер кеширует по запросу?
Мое приложение 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
Атрибут будет использовать его.