如何禁用 Identity 2.0 中的用户?
How to disable a User in Identity 2.0?
我正在尝试找到一种方法来禁用 Identity 2.0 中的用户,但似乎找不到任何相关信息。
我基本上想将用户设置为 IsActive=false,并且希望在创建用户后立即执行此操作。但是,我需要一种方法来为我们的站点管理员设置 IsActive。我已经拥有 ASP.Net 会员资格,但我希望将网站转换为 MVC 和身份。
根据我的要求,我们要求人们继续注册一个帐户,但我们希望它在默认情况下被禁用。然后,当我们收到加入的付款时,我们将返回并启用它们。我们还使用它在订阅到期且未续订时禁用用户。
有没有办法在不删除帐户的情况下禁用帐户或仅将帐户锁定 X 时间?到目前为止,我还没有找到任何方法来禁用 Identity 中的用户,我很惊讶以前没有出现过这个问题。
步骤 #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 步:在 login/logout 操作中使用以下 class,而不是 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
当您创建安装了身份位的站点时,您的站点将有一个名为 "IdentityModels.cs" 的文件。在此文件中有一个名为 ApplicationUser 的 class,它继承自 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
评论里有个不错的link,方便点here
本教程准确地告诉您需要做什么来为您的用户添加自定义属性。
实际上,根本不用看教程。
1) 在ApplicationUserclass中添加一个属性,eg:
public bool? IsEnabled { get; set; }
2) 在您的数据库中的 AspNetUsers table 上添加一个具有相同名称的列。
3) 砰,就是这样!
现在在您的 AccountController 中,您有一个注册操作,如下所示:
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 table.
的新列中
然后,您需要通过覆盖 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);
}
您的里程可能会有所不同,您可能不想 return 该 SignInStatus,但您明白了。
正在对此进行一些研究,结果发现 IdentityUser
基础 class 具有与该主题相关的一些属性。即:LockoutEnabled
和 LockoutEndDateUtc
.
将 LockoutEnabled
设置为 true
并将 LockoutEndDateUtc
设置为将来的某个日期就足够了,以便标准 SignInManager.PasswordSignInAsync
可以选择它并采取相应的行动而无需任何覆盖或自定义。
如果您只想禁用用户而不指定任何确切的重新激活日期,您可以将其设置为 DateTime.MaxValue
。
我正在尝试找到一种方法来禁用 Identity 2.0 中的用户,但似乎找不到任何相关信息。
我基本上想将用户设置为 IsActive=false,并且希望在创建用户后立即执行此操作。但是,我需要一种方法来为我们的站点管理员设置 IsActive。我已经拥有 ASP.Net 会员资格,但我希望将网站转换为 MVC 和身份。
根据我的要求,我们要求人们继续注册一个帐户,但我们希望它在默认情况下被禁用。然后,当我们收到加入的付款时,我们将返回并启用它们。我们还使用它在订阅到期且未续订时禁用用户。
有没有办法在不删除帐户的情况下禁用帐户或仅将帐户锁定 X 时间?到目前为止,我还没有找到任何方法来禁用 Identity 中的用户,我很惊讶以前没有出现过这个问题。
步骤 #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 步:在 login/logout 操作中使用以下 class,而不是 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
当您创建安装了身份位的站点时,您的站点将有一个名为 "IdentityModels.cs" 的文件。在此文件中有一个名为 ApplicationUser 的 class,它继承自 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
评论里有个不错的link,方便点here
本教程准确地告诉您需要做什么来为您的用户添加自定义属性。
实际上,根本不用看教程。
1) 在ApplicationUserclass中添加一个属性,eg:
public bool? IsEnabled { get; set; }
2) 在您的数据库中的 AspNetUsers table 上添加一个具有相同名称的列。
3) 砰,就是这样!
现在在您的 AccountController 中,您有一个注册操作,如下所示:
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 table.
的新列中然后,您需要通过覆盖 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);
}
您的里程可能会有所不同,您可能不想 return 该 SignInStatus,但您明白了。
正在对此进行一些研究,结果发现 IdentityUser
基础 class 具有与该主题相关的一些属性。即:LockoutEnabled
和 LockoutEndDateUtc
.
将 LockoutEnabled
设置为 true
并将 LockoutEndDateUtc
设置为将来的某个日期就足够了,以便标准 SignInManager.PasswordSignInAsync
可以选择它并采取相应的行动而无需任何覆盖或自定义。
如果您只想禁用用户而不指定任何确切的重新激活日期,您可以将其设置为 DateTime.MaxValue
。