2015-10-05 3 views
6

Я пытаюсь найти способ отключить пользователя в Identity 2.0 и не может найти никакой информации об этом.Как отключить пользователя в Identity 2.0?

Я хотел бы установить пользователя IsActive = false и предпочел бы делать это, как только пользователь будет создан. Тем не менее, мне нужен способ установить IsActive для нашего сайта Admin. У меня уже есть это с членством в ASP.Net, но я ищу скрытый сайт для MVC и Identity.

Для моих требований мы просим людей пойти и зарегистрировать учетную запись, но мы хотим, чтобы она была отключена по умолчанию. Затем, когда мы получим оплату за присоединение, мы вернемся и включим их. Мы также используем его, чтобы отключить пользователей, когда их подписка окончена, и они не обновлены.

Есть ли способ отключить учетную запись, не удаляя ее, или только запирание их на Х-время? До сих пор я не нашел никакого способа просто отключить пользователя в Identity, и я удивлен, что этот вопрос не появился раньше.

ответ

11

При создании сайта с идентичностью битами, установленными, ваш сайт будет иметь файл с именем "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, у вас есть действие Регистрация следующим образом:

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) 

Я добавил IsEnabled = истинна на создание объекта ApplicationUser. Теперь значение будет сохранено в вашем новом столбце таблицы AspNetUsers.

Вам необходимо будет обработать это значение как часть процесса входа, переопределив PasswordSignInAsync в ApplicationSignInManager.

Я сделал это следующим образом:

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

Как вы достигаете того же в ASP.NET Core 1.0 с Identity 3.0, который не имеет ApplicationSignInManager или PasswordSignInAsync (...)? – nam

+0

Использование '.Result' противоречит рекомендациям и, как известно, вызывает блокировки в определенных сценариях, оно также блокирует поток, поражающий всю точку асинхронизации. Лучше пометить метод '' PasswordSignInAsync'' как 'async' и вместо' FindByEmailAsync' ждать. – TKharaishvili

+1

Самая большая проблема с этим - если они уже вошли в систему, это не повлияет на них. В частности, если они проверили флажок «Запомни меня». Если они получают доступ к сайту на регулярной основе, им не нужно будет входить в систему. Я пытаюсь выяснить, можно ли использовать эту логику блокировки для этого, и если она лучше подходит для обработки пользователей, которые уже вошли в систему , –

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

+0

Возможно, я смущен об этом или не затронул вопрос. Что я беру из кода, он будет использоваться, чтобы узнать, находится ли пользователь в состоянии Locked Out, которое возникло бы из неудачных попыток входа в систему. Похоже, он устанавливает время выхода из системы и количество неудачных попыток входа в систему перед их блокировкой. Я смотрю, могу ли я просто отключить учетную запись. Выполнение чего-то вроде установки IsActive = false. Таким образом, они просто не могут войти в период. Когда произойдет обновление, я просто сброшу IsActive = true. Что-то похожее на это. Я все равно просмотрю код и посмотрю, сработает ли он. – Caverman

+0

Я хотел выбросить идею, которую я попытаюсь реализовать для отключения пользователя. Я собираюсь создать роль под названием «NoAccess». Тогда на моих контроллерах я не буду включать эту роль как та, которая может попасть в любой ActionResult. В моем случае я буду использовать это как свою роль по умолчанию, когда кто-то зарегистрируется. Я думаю, что это позаботится о моих потребностях. – Caverman

+0

Однако похоже, что мне может потребоваться либо не устанавливать Identity для блокировки после определенных неудачных входов в систему, либо использовать приведенный выше код. Я удивлен, что Microsoft не упростило взглянуть на кого-то, кто был заблокирован и/или более простой способ разблокировать их. – Caverman

3

Проведено некоторое исследование по этому вопросу и получается, что базовый класс IdentityUser обладает некоторыми свойствами, относящимися к этой теме. А именно: LockoutEnabled и LockoutEndDateUtc.

Это достаточно установить LockoutEnabled в true и LockoutEndDateUtc в какой-то дату в будущем для того, чтобы стандартный SignInManager.PasswordSignInAsync, чтобы поднять его и действовать соответствующим образом без каких-либо переопределений или настройки.

И если вы хотите просто отключить пользователя, не указав точную дату реактивации, вы можете просто установить его на DateTime.MaxValue.

Смежные вопросы