Идентификатор ASP.NET, добавьте другого пользователя в роль мгновенно (им не нужно выходить из системы и снова)
Прежде всего, я знаю об этом вопросе: MVC 5 AddToRole требует выхода из системы до его работы?
и этот: Что такое IUserSecurityStampStore <TUser> интерфейс?
поэтому, пожалуйста, не отмечайте это как дубликат.
Я пытаюсь добавить другого пользователя к роли (т.е. пользователь, которого мы добавляем в эту роль, не является текущим пользователем. Если это так, ответ на первый вопрос, к которому я привязан, является достаточным.)
Так же:
IdentityResult result = await userManager.AddToRoleAsync(userID, roleName);
Две ситуации, в которых я делаю это, - это: от страницы администратора, где текущий пользователь является администратором; и webhook, обеспеченный базовой аутентификацией (где вообще нет текущего пользователя).
ПРОБЛЕМА: если пользователь, к которому относится это изменение, входит в систему и использует приложение, мне нужно, чтобы изменения "добавить к роли" применились мгновенно. Им не нужно будет снова и снова выходить из системы, чтобы это произошло, и это должно произойти сразу.
Спасибо всем.
EDIT:
Кстати, User.IsInRole(roleName) требует выхода из системы и входа в систему, чтобы отразить добавление в новую роль. UserManager.IsInRole(userID, roleName) этого не делает, потому что (я предполагаю) он идет прямо к таблицам базы данных, которые нужно проверить. Но если пользователь нажимает на метод действия, защищенный ролью, к которой они только что добавлены, им все равно придется снова войти в систему, что достаточно справедливо. Все еще любопытно, есть ли способ обойти это.
EDIT:
Вот исходный код атрибута Authorize: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/src/System.Web.Mvc/AuthorizeAttribute.cs
В нем используется User.IsInRole, поэтому мы должны снова войти в систему. Кажется, что метод переопределить - AuthorizeCore (HttpContextBase httpContext). Я не храбрый и не достаточно хорош, чтобы покончить с этим прямо сейчас, но если вы хотите, чтобы много людей найдут это полезным.
Ответы
Ответ 1
Начиная со дна вашего вопроса. User.IsInRole()
переходит в файл cookie пользователя и проверяет, какие роли хранятся в этом файле cookie. Следовательно, для перехода к изменениям требуется переход. И да, вы правы, говоря, что UserManager.IsInRole()
проверяет с базой данных, а не с файлом cookie.
Чтобы убедиться, что изменения роли применяются немедленно, вам нужно проверить изменение ролей при каждом запросе. Для этого в Startup.Auth.cs
найдите эту строку:
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(0), // <-- This is zero. Check on every request
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),
Это базовый способ обновления cookie. По умолчанию validateInterval
устанавливается в течение 30 минут. Если вы установите его на ноль, система создаст новый файл cookie с обновленными ролями для каждого запроса. Это может быть слишком большой нагрузкой DB, если у вас достаточно пользователей, поражающих вашу систему одновременно. Поэтому я увеличил бы промежуток времени до 30 секунд - 1-2 минуты.
Эта функция была создана как способ выйти из всех сеансов с помощью одного изменения пароля. Но также хорошо работает для ваших целей.
Ответ 2
В ядре ASP.NET SignInManager.RefreshSignInAsync() решает это.
Ответ 3
Для ASP.NET Core Identity 2 решение должно использовать:
services.Configure<SecurityStampValidatorOptions>(options =>
{
options.ValidationInterval = TimeSpan.FromMinutes(1);
});
Чтобы принудительно обновлять каждую минуту или использовать TimeSpan.Zero для принудительного обновления каждый раз, когда пользователь заходит на страницу (обратите внимание, что каждый раз, когда выполняется запрос к базе данных).
Также убедитесь, что если вы переписываете cookie файлы, не используйте:
services.ConfigureApplicationCookie(options =>
{
options.Events = new CookieAuthenticationEvents(){
...
};
}
Но перезаписать нужные вам события напрямую, так как в противном случае проверка не вызывается:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = ctx => {
...
};
}