在标准 ASP.NET MVC 安装模板中模拟用户

Impersonate a user in a standard ASP.NET MVC installation template

我已经设置了一个标准的 ASP.NET MVC 站点,具有正常的身份验证。我添加了角色,所以新用户获得特定角色。

现在,我希望能够模拟用户。

冒充建议

模仿,当我四处寻找时,是这样的:

     FormsAuthentication.SetAuthCookie(user.UserName, false);

这在默认情况下不起作用,因为您必须做两件事:

1:

启用表单身份验证:

 <system.web>
    <authentication mode="Forms" />
  </system.web>

2:

禁用模块:

<system.webServer>
    <modules>
      <!--<remove name="FormsAuthentication" />-->
    </modules>
    <staticContent>

挑战

然而,这样做会带来一些挑战。

  1. 模拟时无法退出。这很容易被修复 在注销中添加以下内容:FormsAuthentication.SignOut();
  2. User.IsInRole(Constants.Roles.Creditor); 停止工作,所以 我们无法检查用户是否担任角色

怎么办?

这可能归结为我 - 显然 - 尽管尝试过但仍未完全理解成员资格框架。但是,如何才能冒充到这里工作?

我没有明确的理由使用 "Forms" 身份验证,我开始走这条路的唯一原因是模仿。所以我看到我有两个明显的方向:

这里有什么帮助吗? :-)

有很多方法可以实现这一点,您真正需要做的就是将两个 Id 都获取到您的控制器并决定您希望它如何持久化(Cookie、Cache、Db 等)。

执行此操作的一种简单方法是为模拟创建声明并为此类声明添加策略。这是一个 link 用于添加基于索赔的政策。

这里有一些代码可以帮助您入门:

在您的控制器中,您需要一个端点来执行类似这样的操作

        var claims = await UserManager.GetClaimsAsync(CurrentUserId);
        var claim = claims.FirstOrDefault(c => c.Type == "Impersonate");
        if (claim!=null)
        {
            //You may forget to remove it or the user could end there session before you are able to
            var r = await UserManager.RemoveClaimAsync(CurrentUserId, claim);
        }
        var result = await UserManager.AddClaimAsync(CurrentUserId, new Claim("Impersonate", userId));

        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

现在使用上面的代码,我们需要用户 ID,但我们可以很容易地获得角色并将其保存在声明中。从这里你只需要决定你想如何使用这个声明。下面的 link 将向您展示如何做到这一点。

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/claims

请记得在完成后删除声明。

当您有时不得不冒充用户时,这个工具很管用。我为客户工作的一个项目需要能够一次模拟用户数周以完成其他客户的工作。

如果我们需要在基本表单principal中实现IsInRole()方法,我们需要自定义principal。

User 是一个主体对象,它包含 Identities 的列表。 Default身份不包含角色属性,因此我们需要创建自定义身份对象。

例如:

public class CustomPricipal : IPrincipal
{        
    public CustomPricipal(string username)
    {
        this.Identity = new CustomIdentity(username);
    }

    public IIdentity Identity
    {
        get;
        private set;
    }

    public bool IsInRole(string role)
    {
        return this.Identity != null && ((CustomIdentity)this.Identity).Roles.Any(x => x.ToLower() == role.ToLower());
    }
}

public class CustomIdentity : IIdentity
{
    public CustomIdentity(string name)
    {
        // We can fetch the user information from database and create custom properties
        this.Name = name;
        this.IsAuthenticated = true;
        this.AuthenticationType = "Forms";
        this.Roles = new List<string>() { "Admin", "SuperAdmin" };
    }
    public string AuthenticationType
    {
        get;
        private set;
    }

    public bool IsAuthenticated
    {
        get;
        private set;
    }

    public string Name
    {
        get;
        private set;
    }
    public List<string> Roles
    {
        get;
        private set;
    }
}

global.asax.cs

    public override void Init()
    {
        this.PostAuthenticateRequest += MvcApplication_PostAuthenticateRequest;
        base.Init();
    }

    void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
    {
        if (Request.IsAuthenticated)
        {
            HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie != null)
            {
                FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);                    
                Context.User = Thread.CurrentPrincipal = new CustomPricipal(authTicket.Name);
            }
        }
    }

现在我们可以使用 User.IsInRole("")