未在登录请求中设置ASP.NET标识

时间:2015-03-03 12:59:48

标签: asp.net asp.net-mvc asp.net-identity-2

我正在使用带有ClaimsIdentity的ASP.NET身份来验证我的用户身份。对用户进行身份验证后,属性User.Identity将包含ClaimsIdentity实例。

但是,在登录请求期间不是这种情况:

    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, false, shouldLockout: false);
        switch (result)
        {
            case SignInStatus.Success:
                var identity = User.Identity;

------------>   // identity is of type WindowsIdentity  <------------

                return RedirectToLocal(returnUrl);

如您所见,即使登录成功,属性User.Identity尚未设置为ClaimsIdentity实例。我认为这是合理的,这意味着SignInManager不会更新属性,因此我们必须等到下一个请求才能看到登录结果。

但是,我必须在方法PasswordSignInAsync之后执行其他逻辑,因此我需要一种方法来获取 .Success 分支中的ClaimsIdentity实例。 switch语句。

在检查调试器中的SignInManager时,我看到它的类型为Microsoft.Owin.Security.AuthenticationManager,其属性SignInEntry.Item1包含我正在寻找的ClaimsIdentity

但是,类型Microsoft.Owin.Security.AuthenticationManager不公开,所以唯一的方法似乎是使用反射的黑客。

有更好的方法吗?

2 个答案:

答案 0 :(得分:7)

我同意PasswordSignInAsync不会将用户实例作为out参数返回太糟糕了。如果您查看源代码,您可以看到它使用this.UserManager.FindByNameAsync(userName)按userName查找用户,然后使用this.UserManager.CheckPasswordAsync(user, password)验证密码,但用户存储在本地变量中。

我认为这应该被提议作为对SignInManager类的改进。

可能(且效率低下)的解决方法是再次查询用户,然后以与SignInManager.SignInAsync相同的方式创建声明标识:

        ApplicationUser user = await UserManager.FindByNameAsync(model.Email);
        ClaimsIdentity claimsIdentity = await SignInManager.CreateUserIdentityAsync(user);

答案 1 :(得分:3)

通过AuthenticationResponseGrant属性公开身份:

ClaimsIdentity identity = SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity;