首页 文章

PasswordSignInAsync()似乎在没有任何错误的情况下阻塞

提问于
浏览
-1

我正在尝试使用ASP.NET Core Identity 2.0在我现有的应用程序中设置身份验证 . 当我使用自己的数据库模式和类时,我有自己的User类,我必须创建一个自定义UserStore和一个自定义UserManager .

所以我在AccountController中有我的登录功能:

[HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, set lockoutOnFailure: true
            var result = await _signInManager.PasswordSignInAsync(model.Login, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {
                _logger.LogInformation("User logged in.");
                return RedirectToLocal(returnUrl);
            }
            if (result.IsLockedOut)
            {
                _logger.LogWarning("User account locked out.");
                return RedirectToAction(nameof(Lockout));
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Connection failed.");
                return View(model);
            }
        }
        return View(model);
    }

我有自定义UserManager:

public class CustomUserManager<TUser> : UserManager<TUser> where TUser : User
{
public CustomUserManager(IUserStore<TUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TUser> passwordHasher, IEnumerable<IUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TUser>> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
}

public override Task<bool> CheckPasswordAsync(TUser user, string password)
{
    bool passwordIsSimilar = password == user.Password;

    return new Task<bool>(() => passwordIsSimilar);
}
}

我的服务声明:

services.AddIdentity<User, ProfileUser>().AddUserManager<CustomUserManager<User>>().AddDefaultTokenProviders();
        services.AddTransient<IUserStore<User>, UserIdentity>();
        services.AddTransient<IRoleStore<ProfileUser>, ProfileIdentity>();

        services.Configure<IdentityOptions>(options =>
        {
            // Lockout settings
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
            options.Lockout.MaxFailedAccessAttempts = 10;
            options.Lockout.AllowedForNewUsers = true;
        });

        services.ConfigureApplicationCookie(options =>
        {
            // Cookie settings
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
            // If the LoginPath isn't set, ASP.NET Core defaults 
            // the path to /Account/Login.
            options.LoginPath = "/Account/Login";
            // If the AccessDeniedPath isn't set, ASP.NET Core defaults 
            // the path to /Account/AccessDenied.
            options.AccessDeniedPath = "/Account/AccessDenied";
            options.SlidingExpiration = true;
        });

我的自定义UserManager工作,并且在用户登录时调用CheckPasswordAsync() . 但是,在此之后,函数等待_signInManager.PasswordSignInAsync(model.Login,model.Password,model.RememberMe,lockoutOnFailure:false);似乎在某处阻止 . 调试模式中没有错误,并且执行没有传递到下一行(if(result.Succeeded))

您是否了解我的代码在执行中阻止的原因?

1 回答

  • 6

    这里的问题是这一行:

    return new Task<bool>(() => passwordIsSimilar);
    

    Task constructor实际上并没有执行任务;它只是初始化它 . 调用 CheckPasswordAsync 的代码正在等待此任务完成,但由于它从未启动过,所以不会发生这种情况 .

    正如Stephen Cleary writes:不要使用 TaskTask<T> 构造函数 . 相反,在您的示例中,您可以简单地使用Task.FromResult<T>,如下所示:

    return Task.FromResult(passwordIsSimilar);
    

    从本质上讲,这为您创建了一个新的 Task ,它已经完成 passwordIsSimilar 的结果 . 任何解开任务的东西(通常使用 await )都将检索 passwordIsSimilar 的值 .

相关问题