ASP.NET Identity doesn't update Identity infor

2019-04-28 00:15发布

I am working on a single page application using AngularJS and ASP.NET Identity 2. I log the user in and the cookie is set; however, when I check the Identity of the user on the same request, it shows it as blank and IsAuthenticated is false. However, these are populated on subsequent requests. I was hoping to send back to the UI whether or not the user was logged in on the same request. Is this possible?

Code as requested (AngularJS makes AJAX post into WebAPI controller Login method)

[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条回答
戒情不戒烟
2楼-- · 2019-04-28 00:23

I was hoping to send back to the UI whether or not the user was logged in on the same request. Is this possible?

Yes. As said in other responses, you can.

I just want to cover the case when you are in the same request but outside the context where the SignIn took place.

Through Owin, you could use something like this extension method:

    /// <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;
    }
查看更多
SAY GOODBYE
3楼-- · 2019-04-28 00:27

You won't get a signed in identity until the next request because the call to SignIn is what's causing a cookie to be set on the response. That cookie will turn into the identity on subsequent requests, but its too late to change your current request's identity.

查看更多
走好不送
4楼-- · 2019-04-28 00:31

I log the user in and the cookie is set; however, when I check the Identity of the user on the same request, it shows it as blank and IsAuthenticated is false.

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

There is a fairly large pipeline of events that occur. I'm pretty sure MVC runs in the ProcessRequest method. This method is after the AuthenticateRequest event and the PostAuthenticateRequest event. This means that the entire ASP.Net authentication framework can never be updated during the ProcessRequest method. This is why you'll see almost all system do a redirect afterwards, so that the next request has all the authentication (IIdentity, IPrincipal, IsAuthenticated, etc).

I was hoping to send back to the UI whether or not the user was logged in on the same request. Is this possible?

How could the code not be able to? The first request either authenticates them or not, whatever code is doing that knows if they are authenticated.

查看更多
Ridiculous、
5楼-- · 2019-04-28 00:38

When using Owin authentication, the AuthenticationManager.SignIn() method barely sends a message to the cookie handler to set a cookie when the cookie handler gets to handle the request after the Web API Controller (see my blog post Understanding the Owin External Authentication Pipeline for details).

But the Login method returns true if the login was successful and false if not, so you can use that information in the Login action to send back information. If you don't only want to know if the login succeeded or not, but also want the actual identity you can change Login() to return the user in case of successful login and null if failed.

查看更多
登录 后发表回答