Установите прокси-пользователя в 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. Таким образом, он может легко повторно аутентифицировать вас обратно к вашему первоначальному пользователю.
Я получил это работает очень быстро. Используйте его, чтобы позволить администратору войти в систему как кто-либо еще.