ASP.NET MVC 5 成员身份模拟特定用户

ASP.NET MVC 5 Membership impersonate specific user

有很多关于在 c# 中模拟用户的示例,但问题是您必须提供该用户的域、用户名和密码。

我需要的有点不同。如果我们使用成员资格在 ASP.NET MVC 5 中构建应用程序,假设我们具有以下角色:

以及属于不同角色的用户。

现在,如果角色 User 的用户在应用程序中遇到一些问题,我如何允许角色 Admin 的用户模拟该特定用户,而不需要该特定用户向管理员提供他的用户名和密码?

主要是 Admin 应该能够从应用程序中模拟任何用户,并能够以用户本人的身份浏览应用程序。

这可以在 MVC 中实现吗?

有许多应用程序提供这种可能性,Salesforce 就是其中之一。 Salesforce 中的 Admin 可以模拟任何用户,并且 browse/see 应用程序就像用户本人一样。这将使他们能够识别并解决应用程序中可能存在的问题。

我不认为解决方案在于会员系统本身。我可能会在应用程序逻辑中实现模拟。会员系统会告诉您用户的身份以及他们的角色,但您的应用程序可以随意忽略或解释这些角色。

编辑:详细说明...

您可以将此视为应用程序中内置的一组功能,而不是会员资格问题。管理员只需成为管理员就可以看到用户看到的内容 - 这是应用程序逻辑的一部分。

试图将此功能侵入会员系统,从而使应用程序以某种方式被愚弄,将管理员视为不同的会员,这似乎很老套 - 任何对会员系统的滥用都会打开安全漏洞。

如果你真的想走这条路,也许你应该考虑给管理员短期令牌绑定到他们的 IP 地址,比如 10 分钟,让他们以任何人身份登录 - 同样这与会员资格无关 - 它是与密码检查相关联,您可以将其分解。

所以我在这里并没有真正提供解决方案 - 只是建议不要在入侵底层会员系统时找到它。如果您这样做,那么您会削弱会员系统的安全性,但也会限制您可以实现的目标。例如,您可能想向管理员显示用户看到的内容 + 一些额外的诊断信息 - 如果应用程序认为管理员是用户,这将如何工作?

Now if a user from role User has some issues with the application, how can I allow a user from Admin role to impersonate that specific user, without that specific user to give the Admin his username and password? ...Is this possible to achieve in MVC?

这可以在不知道要模拟的用户的密码的情况下完成,但您必须知道要模拟的用户的用户名。

您可以使用正常的表单身份验证通过以下方式执行此操作:

FormsAuthentication.SetAuthCookie("username-to-be-impersonated", false);

当然你会想保护这个代码块的入口,这样只有管理员才能进行模拟。您可能想要做一些其他事情,例如将管理员用户的用户名保存在会话或 cookie 中,以帮助系统知道模拟正在进行中,并让用户能够在完成模拟后撤消它。

最重要的是,会员系统只关心 auth cookie,您可以在不知道用户密码的情况下为任何用户名编写 auth cookie。

ASP.NET Identity 2 的过程相同,不同之处在于您编写身份验证 cookie 的方式。注意下面的代码是 a snippet based on the comment that @trailmax left in the OP:

// assume you already have references to a UserManager and HttpContext
var userToImpersonate = await userManager
    .FindByNameAsync(userNameToImpersonate);
var identityToImpersonate = await userManager
    .CreateIdentityAsync(userToImpersonate,   
        DefaultAuthenticationTypes.ApplicationCookie);
var authenticationManager = httpContext.GetOwinContext().Authentication;
authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
authenticationManager.SignIn(new AuthenticationProperties()
{
    IsPersistent = false
}, identityToImpersonate);

您还应该有一个策略,允许您在让管理员冒充他们的帐户之前以某种方式获得用户的许可。

我所做的只是在会话中传递当前用户 ID 并在整个应用程序中读取会话。如果当前登录的用户与会话对象不同,我知道模拟正在进行。我在会话开始时将所有这些设置在 global.asax 文件中。似乎非常适合我的应用程序。