Установите прокси-пользователя в GenericPrincipal, сохраняя старую идентичность, используя MVC

У меня есть сайт, на котором я разрешаю некоторым пользователям использовать прокси в качестве другого пользователя. Когда они это сделают, они должны видеть весь сайт так, как если бы он был пользователем, в котором он прокси. Я делаю это, изменяя текущий объект пользователя

internal static void SetProxyUser(int userID)
{
    HttpContext.Current.User = GetGenericPrincipal(userID);
}

Этот код прекрасно работает для меня.

На сайте для прокси-доступа пользователь выбирает значение в раскрывающемся списке, которое я отображаю в своем файле _layout, таким образом, чтобы оно отображалось на всех страницах.

 @Html.Action("SetProxyUsers", "Home")

Представление SetProxyUsers выглядит следующим образом:

@using (@Html.BeginForm("SetProxyUsers", "Home")) {

@Html.DropDownList("ddlProxyUser", (SelectList)ViewBag.ProxyUsers_SelectList, new { onchange = "this.form.submit();" })

}

Действия контроллера для этого выглядят так

    [HttpGet]
    public ActionResult SetProxyUsers()
    {
        ViewBag.ProxyUsers_SelectList = GetAvailableProxyUsers(originalUserID);

        return PartialView();
    }

    [HttpPost]
    public ActionResult SetProxyUsers(FormCollection formCollection)
    {
        int id = int.Parse(formCollection["ddlProxyUser"]);

        RolesHelper.SetProxyUser(id);

        ViewBag.ProxyUsers_SelectList = GetAvailableProxyUsers(originalUserID);

        return Redirect(Request.UrlReferrer.ToString());
    }

Все это работает (за исключением переменной originalUserID, которую я вставил здесь, чтобы символизировать то, что я хочу сделать дальше.

Моя проблема в том, что значения в раскрывающемся списке основаны на вошедшем в систему пользователя. Поэтому, когда я меняю пользователя с помощью прокси-сервера, я также изменяю значения в раскрывающемся списке прокси (чтобы он исчез, если "новому" пользователю не разрешен прокси-сервер, или для отображения списка "новых" пользователей доступных прокси-пользователей).).

Мне нужно, чтобы этот список выбора остался без изменений. Как мне сохранить идентификатор оригинального пользователя? Я мог бы сохранить его в переменной сеанса, но я не хочу связываться с потенциальными проблемами тайм-аута, так что это последнее средство.

Пожалуйста, помогите, и дайте мне знать, если что-то неясно с этим вопросом.

Обновить

Я не осознавал, что HttpContext устанавливается для каждого поста. Я до сих пор не работал с такими вещами и по какой-то причине предположил, что я устанавливал значения для всего сеанса (глупо, я знаю). Тем не менее, я использую проверку подлинности Windows. Как я могу изменить пользователя на более постоянной основе (пока открыт браузер)? Я предполагаю, что не могу использовать куки-файлы FormAuthentication, так как я использую Windows в качестве режима аутентификации, верно?

2 ответа

Вместо того, чтобы подделывать аутентификацию, почему бы не сделать ее реальной? На сайте, над которым я работаю, мы позволяем администраторам выдавать себя за других пользователей, устанавливая cookie-файл для аутентификации пользователя. Затем исходный идентификатор пользователя сохраняется в сеансе, поэтому, если они когда-либо выходят из учетной записи олицетворенных пользователей, они фактически автоматически снова входят в свою исходную учетную запись.

Редактировать:

Вот пример кода того, как я делаю олицетворение:

[Authorize] //I use a custom authorize attribute; just make sure this is secured to only certain users.
public ActionResult Impersonate(string email) {
    var user = YourMembershipProvider.GetUser(email);

    if (user != null) {
        //Store the currently logged in username in session so they can be logged back in if they log out from impersonating the user.
        UserService.SetImpersonateCache(WebsiteUser.Email, user.Email);

        FormsAuthentication.SetAuthCookie(user.Email, false);
    }

    return new RedirectResult("~/");
}

Просто как тот! Работает отлично. Единственным сложным моментом является сохранение данных сеанса (что, конечно, не требуется, это была просто приятная возможность предложить моим пользователям, чтобы им не приходилось снова входить в систему под своим именем). Ключ сеанса, который я использую:

string.Format("Impersonation.{0}", username)

куда username имя пользователя, который олицетворяется (значение для этого ключа сеанса - имя пользователя исходного / администратора). Это важно, потому что тогда, когда происходит выход из системы, я могу сказать: "Эй, есть ли для вас какие-либо ключи для олицетворения? Потому что, если это так, я войду в систему как пользователь, сохраненный в сеансе. Если нет, я просто выйти из системы ".

Вот пример метода LogOff:

[Authorize]
public ActionResult LogOff() {
    //Get from session the name of the original user that was logged in and started impersonating the current user.
    var originalLoggedInUser = UserService.GetImpersonateCache(WebsiteUser.Email);

    if (string.IsNullOrEmpty(originalLoggedInUser)) {
        FormsAuthentication.SignOut();
    } else {
        FormsAuthentication.SetAuthCookie(originalLoggedInUser, false);
    }

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

Я использовал пример mvc в комментариях к этой статье http://www.codeproject.com/Articles/43724/ASP-NET-Forms-authentication-user-impersonation чтобы

Он использует FormsAuthentication.SetAuthCookie(), чтобы просто изменить текущий авторизованный cookie, а также сохранить олицетворенную личность пользователя в cookie. Таким образом, он может легко повторно аутентифицировать вас обратно к вашему первоначальному пользователю.

Я получил это работает очень быстро. Используйте его, чтобы позволить администратору войти в систему как кто-либо еще.

Другие вопросы по тегам