如何在Identity 2.0中禁用用户?

时间:2015-10-05 14:37:27

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

我正在尝试找到一种方法来禁用Identity 2.0中的用户,但似乎无法在其上找到任何信息。

我想基本上将用户设置为IsActive = false,并且希望在创建用户后立即执行此操作。但是,我需要一种方法来为我们的网站管理员设置IsActive。我已经拥有ASP.Net会员资格,但我希望将网站转换为MVC和身份。

根据我的要求,我们要求人们继续注册帐户,但我们希望默认情况下禁用该帐户。然后,当我们收到加入付款时,我们将返回并启用它们。我们还使用它来禁用用户订阅时,他们没有续订。

有没有办法在不删除帐户的情况下禁用帐户,或者只将其锁定X段时间?到目前为止,我还没有找到任何方法只是在Identity中禁用用户,我很惊讶这个问题以前没有出现过。

3 个答案:

答案 0 :(得分:12)

当您创建一个安装了标识位的网站时,您的网站将有一个名为" IdentityModels.cs"的文件。在此文件中有一个名为ApplicationUser的类,它继承自IdentityUser。

// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser

评论中有一个很好的链接,方便点击here

本教程将准确告诉您为用户添加自定义属性需要做什么。

实际上,请不要费心去看教程。

1)向ApplicationUser类添加一个属性,例如:

public bool? IsEnabled { get; set; }

2)在数据库的AspNetUsers表中添加一个名称相同的列。

3)繁荣,这就是它!

现在在您的AccountController中,您有一个Register操作,如下所示:

public async Task<ActionResult> Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser { UserName = model.Email, Email = model.Email, IsEnabled = true };
                var result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)

我在创建ApplicationUser对象时添加了IsEnabled = true。该值现在将保留在AspNetUsers表中的新列中。

然后,您需要通过覆盖ApplicationSignInManager中的PasswordSignInAsync来处理检查此值作为登录过程的一部分。

我这样做了:

public override Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool rememberMe, bool shouldLockout)
    {
        var user = UserManager.FindByEmailAsync(userName).Result;

        if ((user.IsEnabled.HasValue && !user.IsEnabled.Value) || !user.IsEnabled.HasValue)
        {
            return Task.FromResult<SignInStatus>(SignInStatus.LockedOut);
        }

        return base.PasswordSignInAsync(userName, password, rememberMe, shouldLockout);
    }

您的里程可能会有所不同,您可能不想退回SignInStatus,但您明白了。

答案 1 :(得分:5)

正在对此进行一些研究,结果发现IdentityUser基类具有与此主题相关的一些属性。即:LockoutEnabledLockoutEndDateUtc

LockoutEnabled设置为true和将LockoutEndDateUtc设置为某个未来日期就足够了,以便标准SignInManager.PasswordSignInAsync可以将其选中并采取相应措施,而无需进行任何覆盖或自定义

如果您想在不指定任何确切的重新启动日期的情况下禁用该用户,则可以将其设置为DateTime.MaxValue

答案 2 :(得分:0)

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

     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
    }

Source