使用 MVC 在 GenericPrincipal 中设置代理用户,同时保留旧标识

本文关键字:保留 标识 用户 代理 MVC GenericPrincipal 设置 使用 | 更新日期: 2023-09-27 18:37:08

我有一个网站,我允许一些用户作为其他用户代理。当他们这样做时,他们应该看到整个网站,就好像他们代理的用户一样。我通过更改当前用户对象来做到这一点

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());
    }

所有这些都有效(除了原始 UserID 变量,我把它放在这里是为了象征我接下来要做的事情。

我的问题是下拉列表中的值基于登录的用户。因此,当我使用代理更改用户时,我还会更改代理下拉列表中的值(如果不允许"新"用户代理,则消失,或者显示"新"用户的可用代理用户列表)。

我需要让这个选择列表保持不变。如何存储原始用户的 ID?我可以将其存储在会话变量中,但我不想弄乱潜在的超时问题,所以这是最后的手段。

帮忙,如果这个问题有任何不清楚的地方,请告诉我。

更新

我没有意识到每个帖子都设置了HttpContext。我以前没有真正使用过这种东西,出于某种原因,我假设我正在为整个会话设置值(我知道很愚蠢)。 但是,我使用的是Windows身份验证。如何更永久地更改用户(只要浏览器处于打开状态)?我假设我不能使用表单身份验证cookie,因为我使用Windows作为我的身份验证模式,对吗?

使用 MVC 在 GenericPrincipal 中设置代理用户,同时保留旧标识

与其伪造身份验证,为什么不让它成为现实呢? 在我工作的网站上,我们允许管理员通过为要模拟的用户设置身份验证 cookie 来模拟其他用户。 然后,原始用户 ID 存储在会话中,因此如果他们从模拟的用户帐户注销,他们实际上会自动重新登录到其原始帐户。

编辑

下面是如何进行模拟的代码示例:

[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被模拟用户的名称(该会话密钥的值是原始/管理员用户的用户名)。 这很重要,因为当注销发生时,我可以说,"嘿,是否有任何模拟密钥? 因为如果是这样,我将以存储在会话中的用户身份登录您。 如果没有,我就把你注销"。

下面是注销方法的示例:

[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 中。这样,它可以轻松地将您重新验证回原始用户。

我很快就让它工作了。使用它来允许管理员以其他任何人身份登录。