Изменение методов UserManagerExtensions System.Security.Principal.WindowsIdentity
Мы используем Identity 2 с MVC 5 для нашего веб-проекта. Требуется уметь настраивать олицетворенного пользователя для веб-приложения в web.config следующим образом
<system.web>
<identity impersonate="true" userName="domain\impersonated" password="password" />
</system.web>
Мы реализовали пользовательский UserManager и настроили аутентификацию следующим образом:
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(MyIdentityContext.Create);
app.CreatePerOwinContext<MyUserManager>(MyUserManager.Create);
app.CreatePerOwinContext<MySignInManager>(MySignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<MyUserManager, MyUser, Guid>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
getUserIdCallback: (claimsIdentity) => (Guid.Parse(claimsIdentity.GetUserId()))),
},
ExpireTimeSpan = TimeSpan.FromMinutes(settingsFacade.GetSessionTimeout())
});
}
}
Мы также реализовали пользовательский UserStore, взаимодействуя с базой данных с помощью EF. Строка подключения настроена на использование Integrated Security=True для использования нашего олицетворенного пользователя для доступа к базе данных.
Мы реализовали AccountController с действием ChangePassword
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ChangePassword(ChangePasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var userGuid = User.Identity.GetUserGuid();
var result = UserManager.ChangePassword(userGuid, model.OldPassword, model.NewPassword);
if (result.Succeeded)
{
var user = UserManager.FindById(User.Identity.GetUserGuid());
if (user != null)
{
SignInManager.SignIn(user, isPersistent: false, rememberBrowser: false);
}
return RedirectToAction("Index", new { Message = AccountMessageId.ChangePasswordSuccess });
}
AddErrors(result);
return View(model);
}
Когда вызывается действие ChangePassword, оно запускается от имени другого пользователя, как и ожидалось. Когда я останавливаюсь на точке останова внутри ChangePassword
System.Security.Principal.WindowsIdentity.GetCurrent().Name = "domain\impersonated"
Когда я захожу в UserManager.ChangePassword и останавливаю отладчик в нашей общедоступной задаче UserStore FindByIdAsync(Guid userId), WindowsIdentity заменяется на пользовательский пул приложений, а не на олицетворенного пользователя. Пользователь приложения не имеет доступа к базе данных. Мы хотим, чтобы только олицетворенный пользователь имел доступ к базе данных.
System.Security.Principal.WindowsIdentity.GetCurrent().Name = "domain\appPoolUser"
Я заметил, когда я заменяю вызов метода синхронизации расширения
UserManager.ChangePassword(userGuid, model.OldPassword, model.NewPassword);
с вызовом метода asych
UserManager.ChangePasswordAsync(userGuid, model.OldPassword, model.NewPassword).Result;
WindowsIdentity не изменяется, и FindByIdAsync работает в олицетворенном пользовательском контексте.
Что мы делаем не так? Почему методы синхронизации и асинхронности ведут себя по-разному. Есть ли какая-либо конфигурация OWIN, которую мы пропускаем, для правильной работы с олицетворением? Спасибо.