Серверная сторона утверждает, что кеширование с аутентификацией Owin
У меня есть приложение, которое использовало FormsAuthentication
, и некоторое время назад я переключил его на использование IdentityModel
from WindowsIdentityFramework
, чтобы я мог воспользоваться проверкой на основе утверждений, но было довольно уродливо использовать и воплощать в жизнь. Итак, теперь я смотрю OwinAuthentication
.
Я смотрю OwinAuthentication
и структуру Asp.Net Identity
. Но реализация Asp.Net Identity
framework только в настоящее время использует EntityModel
, и я использую nHibernate
. Поэтому на данный момент я пытаюсь обойти Asp.Net Identity
и просто использовать Owin Authentication
напрямую. Я, наконец, смог получить рабочий логин, используя подсказки от Как игнорировать макет Identity Framework и просто использовать промежуточное ПО OWIN для получения претензий, которые я ищу? ", но теперь мой cookie с претензиями довольно большой. Когда я использовал IdentityModel
, я смог использовать механизм кеширования на стороне сервера, который кэшировал претензии на сервере, а cookie просто держал простой токен для кэшированной информации. Есть ли аналогичная функция в OwinAuthentication
, или я должен сам ее реализовать?
Я ожидаю, что я буду на одной из этих лодок...
- Файл cookie остается 3KB, ну, это немного большой.
- Включить функцию, похожую на
IdentityModel
SessionCaching в Owin
, о которой я не знаю.
- Напишите мою собственную реализацию для кэширования информации, вызывающей раздувание куки файлов, и посмотрите, могу ли я подключить его, когда я настраиваю
Owin
при запуске приложения.
-
Я делаю все это неправильно, и есть подход, о котором я не думал, или что-то неправильно в Owin
.
public class OwinConfiguration
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Application",
AuthenticationMode = AuthenticationMode.Active,
CookieHttpOnly = true,
CookieName = "Application",
ExpireTimeSpan = TimeSpan.FromMinutes(30),
LoginPath = "/Login",
LogoutPath = "/Logout",
ReturnUrlParameter="ReturnUrl",
SlidingExpiration = true,
Provider = new CookieAuthenticationProvider()
{
OnValidateIdentity = async context =>
{
//handle custom caching here??
}
}
//CookieName = CookieAuthenticationDefaults.CookiePrefix + ExternalAuthentication.ExternalCookieName,
//ExpireTimeSpan = TimeSpan.FromMinutes(5),
});
}
}
UPDATE
Я смог получить желаемый эффект, используя информацию, предоставленную Hongye, и я придумал логику ниже...
Provider = new CookieAuthenticationProvider()
{
OnValidateIdentity = async context =>
{
var userId = context.Identity.GetUserId(); //Just a simple extension method to get the ID using identity.FindFirst(x => x.Type == ClaimTypes.NameIdentifier) and account for possible NULLs
if (userId == null) return;
var cacheKey = "MyApplication_Claim_Roles_" + userId.ToString();
var cachedClaims = System.Web.HttpContext.Current.Cache[cacheKey] as IEnumerable<Claim>;
if (cachedClaims == null)
{
var securityService = DependencyResolver.Current.GetService<ISecurityService>(); //My own service to get the user roles from the database
cachedClaims = securityService.GetRoles(context.Identity.Name).Select(role => new Claim(ClaimTypes.Role, role.RoleName));
System.Web.HttpContext.Current.Cache[cacheKey] = cachedClaims;
}
context.Identity.AddClaims(cachedClaims);
}
}
Ответы
Ответ 1
Связность аутентификации cookie OWIN для cookie не поддерживает кеширование сеанса, как функция. # 2 не является параметром.
# 3 - правильный путь. Как предложил Прабху, вы должны сделать следующее в своем коде:
OnResponseSignIn:
- Сохранить контекст.Идентичность в кеше с уникальным ключом (GUID)
- Создайте новый элемент ClaimsIdentity, встроенный с уникальным ключом
- Заменить context.Identity с новым идентификатором
OnValidateIdentity:
- Получить уникальное ключевое требование из контекста. Идентификация
- Получить кешированный идентификатор с помощью уникального ключа
- контекст вызова .ReplaceIdentity с кэшированным идентификатором
Я собирался предложить вам gzip cookie, но я обнаружил, что OWIN уже сделал это в своем TicketSerializer. Не вариант для вас.
Ответ 2
Provider = new CookieAuthenticationProvider()
{
OnResponseSignIn = async context =>
{
// This is the last chance before the ClaimsIdentity get serialized into a cookie.
// You can modify the ClaimsIdentity here and create the mapping here.
// This event is invoked one time on sign in.
},
OnValidateIdentity = async context =>
{
// This method gets invoked for every request after the cookie is converted
// into a ClaimsIdentity. Here you can look up your claims from the mapping table.
}
}
Ответ 3
Вы можете реализовать IAuthenticationSessionStore для хранения файлов cookie в базе данных.
Здесь пример сохранения cookie в redis.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
SessionStore = new RedisSessionStore(new TicketDataFormat(dataProtector)),
LoginPath = new PathString("/Auth/LogOn"),
LogoutPath = new PathString("/Auth/LogOut"),
});
Посмотрите полный пример здесь