【问题标题】:ASP.net Identity Disable UserASP.net 身份禁用用户
【发布时间】:2016-08-06 03:33:11
【问题描述】:

在 MVC 5 中使用新的 ASP.net 身份,我们如何禁止用户登录?我不想删除他们,也许只是暂时停用他们的帐户。

是否有人对此有任何想法,因为我在 ASPNetUsers 表上看不到状态列或任何内容。

【问题讨论】:

  • 恕我直言,关闭这个问题是错误的。 OP 不要求提供代码。问题是是否可以使用 Asp.net 身份框架禁用/锁定帐户。在这种情况下,要求 OP 为他的问题提供“尝试的解决方案”似乎是不合理的,如果他可以的话,他一开始就不必问。我还认为,即使像 Brock Allen 这样的安全专家在他的博文brockallen.com/2013/10/20/… 中提出了一个非常相似的问题,这一事实也表明这是一个相关的问题。
  • 这怎么跑题了?我有完全相同的问题。
  • 我很惊讶 ASP.Net 身份在其当前状态下是多么不完整。为什么要在架构中为您不支持的内容提供列?

标签: asp.net-mvc-5 asp.net-identity


【解决方案1】:
await userManager.SetLockoutEnabledAsync(applicationUser.Id, true);
await userManager.SetLockoutEndDateAsync(DateTime.Today.AddYears(10));

【讨论】:

  • 这应该是正确的答案,因为 OP 询问如何禁用用户,这是迄今为止最简单的解决方案。
  • 使用 await userManager.SetLockoutEndDateAsync(applicationUser.Id, DateTimeOffset.MaxValue);
  • 如何解锁用户??
  • 根据代码,如果您提供MinValueDateTimeOffset,它将在数据库中设置一个null,它应该被解锁。
【解决方案2】:

更新:正如 CountZero 指出的那样,如果您使用的是 v2.1+,那么您应该先尝试使用他们添加的锁定功能,然后再尝试以下解决方案。有关完整示例,请参阅他们的博客文章:http://blogs.msdn.com/b/webdev/archive/2014/08/05/announcing-rtm-of-asp-net-identity-2-1-0.aspx


2.0 版具有可用于锁定用户的 IUserLockoutStore 接口,但缺点是除了 UserManager 类公开的传递方法之外,没有 OOB 功能可以实际利用它。例如,如果它将锁定计数作为标准用户名/密码验证过程的一部分实际增加,那就太好了。但是,自己实现是相当简单的。

第 1 步:创建实现 IUserLockoutStore 的自定义用户存储。

// I'm specifying the TKey generic param here since we use int's for our DB keys
// you may need to customize this for your environment
public class MyUserStore : IUserLockoutStore<MyUser, int>
{
    // IUserStore implementation here

    public Task<DateTimeOffset> GetLockoutEndDateAsync(MyUser user)
    {
        //..
    }

    public Task SetLockoutEndDateAsync(MyUser user, DateTimeOffset lockoutEnd)
    {
        //..
    }

    public Task<int> IncrementAccessFailedCountAsync(MyUser user)
    {
        //..
    }

    public Task ResetAccessFailedCountAsync(MyUser user)
    {
        //..
    }

    public Task<int> GetAccessFailedCountAsync(MyUser user)
    {
        //..
    }

    public Task<bool> GetLockoutEnabledAsync(MyUser user)
    {
        //..
    }

    public Task SetLockoutEnabledAsync(MyUser user, bool enabled)
    {
        //..
    }
}

第 2 步:在登录/注销操作中使用以下类代替 UserManager,将自定义用户存储的实例传递给它。

public class LockingUserManager<TUser, TKey> : UserManager<TUser, TKey>
    where TUser : class, IUser<TKey> 
    where TKey : IEquatable<TKey> 
{
    private readonly IUserLockoutStore<TUser, TKey> _userLockoutStore;

    public LockingUserManager(IUserLockoutStore<TUser, TKey> store)
        : base(store)
    {
        if (store == null) throw new ArgumentNullException("store");

        _userLockoutStore = store;
    }

    public override async Task<TUser> FindAsync(string userName, string password)
    {
        var user = await FindByNameAsync(userName);

        if (user == null) return null;

        var isUserLockedOut = await GetLockoutEnabled(user);

        if (isUserLockedOut) return user;

        var isPasswordValid = await CheckPasswordAsync(user, password);

        if (isPasswordValid)
        {
            await _userLockoutStore.ResetAccessFailedCountAsync(user);
        }
        else
        {
            await IncrementAccessFailedCount(user);

            user = null;
        }

        return user;
    }

    private async Task<bool> GetLockoutEnabled(TUser user)
    {
        var isLockoutEnabled = await _userLockoutStore.GetLockoutEnabledAsync(user);

        if (isLockoutEnabled == false) return false;

        var shouldRemoveLockout = DateTime.Now >= await _userLockoutStore.GetLockoutEndDateAsync(user);

        if (shouldRemoveLockout)
        {
            await _userLockoutStore.ResetAccessFailedCountAsync(user);

            await _userLockoutStore.SetLockoutEnabledAsync(user, false);

            return false;
        }

        return true;
    }

    private async Task IncrementAccessFailedCount(TUser user)
    {
        var accessFailedCount = await _userLockoutStore.IncrementAccessFailedCountAsync(user);

        var shouldLockoutUser = accessFailedCount > MaxFailedAccessAttemptsBeforeLockout;

        if (shouldLockoutUser)
        {
            await _userLockoutStore.SetLockoutEnabledAsync(user, true);

            var lockoutEndDate = new DateTimeOffset(DateTime.Now + DefaultAccountLockoutTimeSpan);

            await _userLockoutStore.SetLockoutEndDateAsync(user, lockoutEndDate);
        }
    }
}

示例

    [AllowAnonymous]
    [HttpPost]
    public async Task<ActionResult> Login(string userName, string password)
    {
        var userManager = new LockingUserManager<MyUser, int>(new MyUserStore())
        {
            DefaultAccountLockoutTimeSpan = /* get from appSettings */,
            MaxFailedAccessAttemptsBeforeLockout = /* get from appSettings */
        };

        var user = await userManager.FindAsync(userName, password);

        if (user == null)
        {
            // bad username or password; take appropriate action
        }

        if (await _userManager.GetLockoutEnabledAsync(user.Id))
        {
            // user is locked out; take appropriate action
        }

        // username and password are good
        // mark user as authenticated and redirect to post-login landing page
    }

如果您想手动锁定某人,您可以设置您要签入MyUserStore.GetLockoutEnabledAsync() 的任何标志。

【讨论】:

  • 根据名称,存储在数据库中的锁定日期应为 UTC。您将其与本地 DateTime.Now 进行比较。
  • 更正:我没有注意到它与 DateTimeOffset 进行了比较。
  • GetLockoutEnabledAsync 不检查用户是否被锁定。顾名思义,它会检查锁定是否已启用。
【解决方案3】:

你可以有一个新类,它应该派生自 IdentityUser 类。您可以在新类中添加一个布尔属性,并且可以使用这个新属性,每次检查都要小心登录过程。我也做得很好。我可能想看看:blog

【讨论】:

    【解决方案4】:

    UserManager.RemovePasswordAsync("userId") 将有效地禁用用户。如果用户没有密码,他将无法登录。您需要设置一个新密码才能再次启用该用户。

    【讨论】:

    • 没有比这更好的选择了吗?
    • 然后用户重置他的密码,瞧!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 2021-12-04
    • 1970-01-01
    相关资源
    最近更新 更多