我在ASP.NET Core 2 MVC应用程序中实现了用户存储。请参阅下面的实施代码。我在Startup中设置了选项,并在AccountController中的lockoutOnFailure: true
方法上设置了PasswordSignInAsync()
。
由于某种原因,未在用户存储上调用访问失败的方法。并且只有" GetLockoutEnabledAsync()"被称为。
当前的实现非常适合常规登录。我可以毫无问题地登录。但是当测试失败的登录时,我不确定我错过了什么来让它使用锁定并且失败计数正确。
public class MyUser : IdentityUser<int>
{
//...
//AccessFailedCount, LockoutEnd, and LockoutEnabled are apart of IdentityUser
//...
}
public class AccountController : Controller
{
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
//...
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: true);
//...
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddIdentity<MyUser, MyRole>(a =>
{
//...
a.Lockout.AllowedForNewUsers = true;
a.Lockout.DefaultLockoutTimeSpan = new System.TimeSpan(0, 5, 0);
a.Lockout.MaxFailedAccessAttempts = 5;
})
.AddDefaultTokenProviders()
.AddSignInManager<SignInManager<MyUser>>()
.AddUserStore<MyUserStore>()
.AddRoleStore<MyRoleStore>();
//...
}
}
public class MyUserStore : IUserStore<MyUser>, IUserRoleStore<MyUser>,
IUserPasswordStore<MyUser>, IUserEmailStore<MyUser>, IUserLockoutStore<MyUser>
{
//...
#region IUserLockoutStore interface
public async Task<DateTimeOffset?> GetLockoutEndDateAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Cannot get lockout end date. User is null.");
}
return user.LockoutEnd;
}
public async Task SetLockoutEndDateAsync(MyUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Cannot set lockout end date. User is null.");
}
user.LockoutEnd = lockoutEnd;
}
public async Task<int> IncrementAccessFailedCountAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Cannot update AccessFailedCount. User is null.");
}
user.AccessFailedCount += 1;
return user.AccessFailedCount;
}
public async Task ResetAccessFailedCountAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Cannot update AccessFailedCount. User is null.");
}
user.AccessFailedCount = 0;
}
public async Task<int> GetAccessFailedCountAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Cannot get AccessFailedCount. User is null.");
}
return user.AccessFailedCount;
}
public async Task<bool> GetLockoutEnabledAsync(MyUser user, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Cannot get LockoutEnabled. User is null.");
}
return user.LockoutEnabled;
}
public async Task SetLockoutEnabledAsync(MyUser user, bool enabled, CancellationToken cancellationToken)
{
if (user == null)
{
throw new ArgumentException("Cannot set LockoutEnabled. User is null.");
}
user.LockoutEnabled = enabled;
}
#endregion
}
答案 0 :(得分:0)
这是行不通的,因为我做错了什么,还有一个错误(技术上我做错了两件事)。
为了解决这个问题,我最终从GitHub(https://github.com/aspnet/Identity)获取了身份代码并为SignInManager和UserManager创建了“自定义”类,因此我可以逐步完成代码。然后将它们临时添加到IoC容器
services.AddIdentity<MyUser, MyRole>(a =>
{
a.Password.RequiredLength = 10;
a.Password.RequireLowercase = true;
a.Password.RequireUppercase = true;
a.User.AllowedUserNameCharacters = null;
a.User.RequireUniqueEmail = true;
a.Lockout.AllowedForNewUsers = true;
a.Lockout.DefaultLockoutTimeSpan = new System.TimeSpan(0, 5, 0);
a.Lockout.MaxFailedAccessAttempts = 5;
})
.AddDefaultTokenProviders()
.AddSignInManager<MySignInManager>() //<-----
.AddUserManager<MyUserManager>() //<-----
.AddUserStore<MyUserStore>()
.AddRoleStore<MyRoleStore>();