SigninManager不调用AccessFailed和Lockout方法

时间:2018-06-09 22:17:39

标签: c# asp.net-core asp.net-core-identity

我在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
}

1 个答案:

答案 0 :(得分:0)

这是行不通的,因为我做错了什么,还有一个错误(技术上我做错了两件事)。

  • 我使用的是不存在的用户帐户(拼写错误,没有抓住它)。由于帐户访问是在基线UserManager中处理的,因此我没有得到明确的消息。
  • 我也遇到了AutoMapper的映射问题,我没有在Identity用户和EF模型之间正确映射访问失败计数。

为了解决这个问题,我最终从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>();