简体   繁体   中英

Customized ASP.Net Identity login works, but IsAuthenticated doesn't

I'm working with an empty/new MVC5 web project with Identity turned on. I've customized the IdentityModel.cs to use our tables/schema to get user logins.

I can login and get the SignInStatus.Success , but then when the page loads the _LoginPartial.cshtml file, it's acting like Request.IsAuthenticated == false . Is there something I missed when overriding?

My AccountController.cs method looks like this:

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

    // This doesn't count login failures towards account lockout
    // To enable password failures to trigger account lockout, change to shouldLockout: true
    var result = await CustomSignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
    switch (result)
    {
        case SignInStatus.Success:
            return RedirectToLocal(returnUrl);
        case SignInStatus.LockedOut:
            return View("Lockout");
        case SignInStatus.RequiresVerification:
            return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
        case SignInStatus.Failure:
        default:
            ModelState.AddModelError("", "Invalid login attempt.");
            return View(model);
    }
}

Here are the supporting custom classes:

public class CustomSignInManager : SignInManager<CustomUser, string>
{
    public CustomSignInManager(CustomUserManager userManager, IAuthenticationManager authenticationManager)
        : base(userManager, authenticationManager)
    {
    }

    public static CustomSignInManager Create(IdentityFactoryOptions<CustomSignInManager> options, IOwinContext context)
    {
        return new CustomSignInManager(context.GetUserManager<CustomUserManager>(), context.Authentication);
    }

    public override async Task<SignInStatus> PasswordSignInAsync(
        string userName,
        string password,
        bool isPersistent,
        bool shouldLockout)
    {
        if (UserManager == null)
        {
            return SignInStatus.Failure;
        }

        var user = await UserManager.FindByNameAsync(userName).WithCurrentCulture();
        if (user == null)
        {
            return SignInStatus.Failure;
        }

        if (UserManager.SupportsUserPassword
            && await UserManager.CheckPasswordAsync(user, password)
                                .WithCurrentCulture())
        {
            return SignInStatus.Success;
        }
        if (shouldLockout && UserManager.SupportsUserLockout)
        {
            // If lockout is requested, increment access failed count
            // which might lock out the user
            await UserManager.AccessFailedAsync(user.Id).WithCurrentCulture();
            if (await UserManager.IsLockedOutAsync(user.Id).WithCurrentCulture())
            {
                return SignInStatus.LockedOut;
            }
        }
        return SignInStatus.Failure;
    }
}

My CustomUserManager:

public class CustomUserManager : UserManager<CustomUser>
{
    public CustomUserManager(IUserStore<CustomUser> store)
        : base(store)
    {
        this.PasswordHasher = new SQLPasswordHasher();
    }

    public static CustomUserManager Create()
    {
        var manager = new CustomUserManager(new CustomUserStore());
        return manager;
    }

    public override bool SupportsUserLockout {
        get { return false; } 
    }

    public override bool SupportsUserPassword
    {
        get { return true; }
    }

    // CheckPasswordAsync
    public override Task<bool> CheckPasswordAsync(CustomUser user, string password)
    {
        return Task.Run(() => MyCheckPasswordAsync( user, password));
    }

    private bool MyCheckPasswordAsync(CustomUser user, string password)
    {
        using (var db = new MkpContext())
        {
            var profile = (
                from pi in db.ProfileIdentifier
                join p in db.Profile on pi.ProfileId equals p.ProfileId
                where
                    pi.ProfileIdentifierTypeId == (int) ProfileIdentifierTypes.email &&
                    pi.ProfileIdentifierValue == user.UserName &&
                    pi.IsActive
                select p).FirstOrDefault(); // Use email to find profileId

            if (profile == null || profile.ProfileId == Guid.Empty) return false;

            // Verify password
            var verPassResults = PasswordHasher.VerifyHashedPassword(profile.Password + "|" + profile.PasswordSalt,
                password);

            // Check if valid password
            if (verPassResults == PasswordVerificationResult.Failed || password == string.Empty) return false;
        }

        return true;
    }
}

Because you simply don't sign in the user at all! You just check if the user can sign in then return success result instead of actual sign in. Simply alter your PasswordSignInAsync() method like this:

public override async Task<SignInStatus> PasswordSignInAsync(
    string userName,
    string password,
    bool isPersistent,
    bool shouldLockout)
{
    // other parts

    if (UserManager.SupportsUserPassword
        && await UserManager.CheckPasswordAsync(user, password)
                            .WithCurrentCulture())
    {
        // this method actually do the job
        return await SignInOrTwoFactor(user, isPersistent).WithCurrentCulture();
    }

    // rest of code
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM