ASP.NET标识不会更新同一请求的标识信息

时间:2014-07-09 18:14:26

标签: c# asp.net asp.net-identity owin claims-based-identity

我正在使用AngularJS和ASP.NET Identity 2处理单页应用程序。我将用户登录并设置了cookie;但是,当我在同一请求中检查用户的身份时,它会将其显示为空白,并且IsAuthenticated为false。但是,这些都会在后续请求中填充。我希望无论用户是否在同一请求中登录,都会向UI发回。这可能吗?

按要求编写代码(AngularJS将AJAX发布到WebAPI控制器登录方法中)

[HttpPost]
[AllowAnonymous]
[Route("Login")]
public async Task<IHttpActionResult> Login(LoginModel loginModel)
{
    var result = await _securityService.Login(loginModel.UserName, loginModel.Password);
    if (!result)
    {
        ModelState.AddModelError("errorMessage", "Invalid username or password.");
        return BadRequest(ModelState);
    }
    return Ok();
}

public async Task<bool> Login(string userName, string password, bool persistCookie = false)
{
    var user = await _userManager.FindAsync(userName, password);
    if (user != null)
        await SignInAsync(user, persistCookie);
    else
        return false;

    return true;
}

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    _authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    _authenticationManager.SignIn(new AuthenticationProperties() {IsPersistent = isPersistent}, await CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie));
}

public Task<ClaimsIdentity> CreateIdentity(ApplicationUser user, string authenticationType)
{
    return _userManager.CreateIdentityAsync(user, authenticationType);
}

4 个答案:

答案 0 :(得分:5)

在下一个请求之前,您不会获得已登录的身份,因为对SignIn的调用是导致在响应上设置cookie的原因。该cookie将在后续请求中变为身份,但是为时已晚,无法更改当前请求的身份。

答案 1 :(得分:2)

使用Owin身份验证时,AuthenticationManager.SignIn()方法几乎不向cookie处理程序发送消息,以便在Cookie处理程序在Web API控制器之后处理请求时设置cookie(请参阅我的博文{{3}有关详情)。

但如果登录成功,则Login方法会返回true,如果没有,则false会返回Login,因此您可以在Login()操作中使用该信息来发回信息。如果您不仅想知道登录是否成功,而且还想要实际身份,则可以更改null以在成功登录时返回用户,如果失败则返回{{1}}。

答案 2 :(得分:0)

  

我将用户登录并设置了cookie;但是,当我在同一请求中检查用户的身份时,它会将其显示为空白,并且IsAuthenticated为false。

This is just a lack of knowledge on your part about how the ASP.Net pipeline works

发生了相当大的事件管道。我非常确定MVC在ProcessRequest方法中运行。此方法位于AuthenticateRequest事件和PostAuthenticateRequest事件之后。这意味着在ProcessRequest方法期间永远不能更新整个ASP.Net身份验证框架。这就是为什么您会看到几乎所有系统都在之后进行重定向,以便下一个请求具有所有身份验证(IIdentity,IPrincipal,IsAuthenticated等)。

  

我希望无论用户是否在同一请求中登录,都会向UI发回。这可能吗?

代码怎么能不能?第一个请求是否对它们进行身份验证,无论代码是什么,都知道它们是否经过身份验证。

答案 3 :(得分:0)

  

我希望无论用户是否在同一请求中登录,都会向UI发回。这可能吗?

是。正如其他回复中所述,你可以。

我只是想在你处于相同的请求时但是在SignIn发生的上下文之外的情况下覆盖这个案例。

通过Owin,你可以使用类似这种扩展方法的东西:

    /// <summary>
    /// Check if the user was authenticated in the current request, or in a previous one
    /// </summary>
    public static bool IsUserAuthenticated(this IOwinContext context)
    {
        if (context.Request.User.Identity.IsAuthenticated)
            return true;

        if (null != context.Authentication.AuthenticationResponseGrant && null != context.Authentication.AuthenticationResponseGrant.Identity)
        {
            return context.Authentication.AuthenticationResponseGrant.Identity.IsAuthenticated;
        }

        return false;
    }