1

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

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 作为我的身份验证模式,对吗?

4

2 回答 2

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

这是 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");
}
于 2012-06-14T19:27:00.533 回答
0

我在这篇文章http://www.codeproject.com/Articles/43724/ASP-NET-Forms-authentication-user-impersonation的评论中使用了 mvc 示例来

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

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

于 2012-06-14T19:58:31.573 回答