我正在尝试使用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 回答
这里的问题是这一行:
Task
constructor实际上并没有执行任务;它只是初始化它 . 调用CheckPasswordAsync
的代码正在等待此任务完成,但由于它从未启动过,所以不会发生这种情况 .正如Stephen Cleary writes:不要使用
Task
或Task<T>
构造函数 . 相反,在您的示例中,您可以简单地使用Task.FromResult<T>,如下所示:从本质上讲,这为您创建了一个新的
Task
,它已经完成passwordIsSimilar
的结果 . 任何解开任务的东西(通常使用await
)都将检索passwordIsSimilar
的值 .