Как использовать ASP.NET Identity 2.0, чтобы позволить пользователю олицетворять другого пользователя?

Я переношу приложение ASP.NET MVC 5.1 из MembershipProvider в ASP.NET Identity v2.0. Одной из особенностей, которые у меня есть в приложении, является олицетворение пользователя: администраторы могут регистрироваться как любой другой пользователь, зарегистрированный на сайте, не зная паролей.

Я использовал этот код для реализовать олицетворение пользователя для MembershipProvider, и это не работает с библиотекой Identity.

Как реализовать олицетворение пользователя (не олицетворение IIS) в Identity ASP.NET?

Ответ 1

Я нашел решение этой проблемы.

В основном я добавляю заявку с именем администратора, если это утверждение существует, я знаю, что происходит олицетворение. Когда администратор хочет прекратить олицетворение, система извлекает исходное имя пользователя для претензий, удаляет старый вымышленный файл cookie и создает новый файл cookie для администратора:

[AuthenticateAdmin] // <- make sure this endpoint is only available to admins
public async Task ImpersonateUserAsync(string userName)
{
    var context = HttpContext.Current;

    var originalUsername = context.User.Identity.Name;

    var impersonatedUser = await userManager.FindByNameAsync(userName);

    var impersonatedIdentity = await userManager.CreateIdentityAsync(impersonatedUser, DefaultAuthenticationTypes.ApplicationCookie);
    impersonatedIdentity.AddClaim(new Claim("UserImpersonation", "true"));
    impersonatedIdentity.AddClaim(new Claim("OriginalUsername", originalUsername));

    var authenticationManager = context.GetOwinContext().Authentication;
    authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
    authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, impersonatedIdentity);
}

Дополнительная информация на моем блоге: Пользовательский олицетворение с помощью ASP.Net Identity 2.

Олицетворение пользователей в Core Asp.Net

Обновление июля 2017 года: эта тема довольно популярна, поэтому я рассмотрел олицетворение пользователей в Core и принципы очень похожи с обновленным API. Вот как олицетворять:

    [Authorize(Roles = "Admin"] // <-- Make sure only admins can access this 
    public async Task<IActionResult> ImpersonateUser(String userId)
    {
        var currentUserId = User.GetUserId();

        var impersonatedUser = await _userManager.FindByIdAsync(userId);

        var userPrincipal = await _signInManager.CreateUserPrincipalAsync(impersonatedUser);

        userPrincipal.Identities.First().AddClaim(new Claim("OriginalUserId", currentUserId));
        userPrincipal.Identities.First().AddClaim(new Claim("IsImpersonating", "true"));

        // sign out the current user
        await _signInManager.SignOutAsync();

        // If you use asp.net core 1.0
        await HttpContext.Authentication.SignInAsync(cookieOptions.ApplicationCookieAuthenticationScheme, userPrincipal);
        // If you use asp.net core 2.0 (the line above is deprecated)
        await HttpContext.SignInAsync(cookieOptions.ApplicationCookieAuthenticationScheme, userPrincipal);

        return RedirectToAction("Index", "Home");
    }

Вот как остановить олицетворение:

    [Authorize(Roles = "Admin"] // <-- Make sure only admins can access this 
    public async Task<IActionResult> StopImpersonation()
    {
        if (!User.IsImpersonating())
        {
            throw new Exception("You are not impersonating now. Can't stop impersonation");
        }

        var originalUserId = User.FindFirst("OriginalUserId").Value;

        var originalUser = await _userManager.FindByIdAsync(originalUserId);

        await _signInManager.SignOutAsync();

        await _signInManager.SignInAsync(originalUser, isPersistent: true);

        return RedirectToAction("Index", "Home");
    }

Полное объяснение в моем блоге: http://tech.trailmax.info/2017/07/user-impersonation-in-asp-net-core/ Полный образец кода на GitHub: https://github.com/trailmax/AspNetCoreImpersonation

Ответ 2

Только для тех, кто использует идентификатор Asp Net Core Identity, это код для решения исходной проблемы (администратор, который хочет ввести пользователя, не зная пароля). Следующее решение не является реальным "олицетворением" с токеном, как в голосованном ответе:

   [Authorize("Administrator")]
   public async Task<IActionResult> ImpersonateUserAsync(string email)
    {            
        var impersonatedUser = await _userManager.FindByNameAsync(email); //Usually username is the email
        await _signInManager.SignOutAsync(); //signout admin
        await _signInManager.SignInAsync(impersonatedUser,false); //Impersonate User

        return RedirectToAction("Index","Home");
    }