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

时间:2012-06-14 19:22:37

标签: c# asp.net-mvc httpcontext genericprincipal

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

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变量之外,我在这里设置了象征我接下来要做的事情。

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

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

请帮忙,如果对此问题有任何疑问,请告诉我。

更新

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

2 个答案:

答案 0 :(得分:2)

不是伪造身份验证,为什么不让它真实?在我工作的网站上,我们让管理员通过为用户设置身份验证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是被模拟用户的名称(该会话密钥的值是原始/ admin用户的用户名)。这很重要,因为当注销发生时,我可以说,"嘿,你有没有假冒的钥匙?因为如果是这样,我将以会话中存储的用户身份登录。如果没有,我会告诉你"。

这是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");
}

答案 1 :(得分:0)

我在本文http://www.codeproject.com/Articles/43724/ASP-NET-Forms-authentication-user-impersonation

的评论中使用了mvc示例

它使用FormsAuthentication.SetAuthCookie()来更改当前授权的cookie,并将模拟的用户身份存储在cookie中。这样,它可以轻松地将您重新验证回原始用户。

我很快就开始工作了。使用它可以让管理员像其他人一样登录。