Custom ASP.NET Identity 2.0 UserStore - Is implementing all interfaces required?

前端 未结 3 983
醉酒成梦
醉酒成梦 2021-02-07 04:18

I\'ve created a custom IUserStore for my application. I\'ve implemented the interfaces I need,

   IUserStore,
           


        
相关标签:
3条回答
  • 2021-02-07 04:37

    I had the same problem and I don't want to implement the IUserTwoFactorStore<TUser, TKey> just to say that I don't implement it. But I also don't want to go back and muck around if I end up wanting to implement it (which I anticipate I will). So what I consider a future proof (and reusable) solution would be: (inspired by @gjsduarte's answer)

    public class SafeUserManager<TUser, TKey> : UserManager<TUser, TKey>
    {
        public override Task<bool> GetTwoFactorEnabledAsync(TKey userId)
        {
            return Store is IUserTwoFactorStore<TUser, TKey>
                ? base.GetTwoFactorEnabledAsync(userId)
                : Task.FromResult(false);
        }
    }
    

    It would probably be a good idea to do the same for the other Get[feature]EnabledAsync(TKey userId) methods.

    0 讨论(0)
  • 2021-02-07 04:41

    Actually the IUserTwoFactorStore interface is really simple, so far my implementation (I don't use two factor auth either) is this:

     ....
     public Task<bool> GetTwoFactorEnabledAsync(User user)
     {
         return Task.FromResult(false);
     }
    
     public Task SetTwoFactorEnabledAsync(User user, bool enabled)
     {
         throw new NotImplementedException();
     }
    

    It works, although I just did it couple minutes ago and didn't test whole app thoroughly.

    0 讨论(0)
  • 2021-02-07 04:44

    I had the same problem. For the moment, as the SignInManager.SignInOrTwoFactor method blindly checks for the GetTwoFactorAuthentication it throws an exception when the UserStore doesn't implement the IUserTwoFactorStore.

    I believe Microsoft intended that the SignInManager PasswordSignInAsync method must be overriden in a custom SignInManager class. Unfortunately I couldn't find any documentation or samples pointing so.

    Here is the SignInManager wrapper class I implemented to solve this issue:

    public class EnhancedSignInManager<TUser, TKey> : SignInManager<TUser, TKey>
        where TUser : class, IUser<TKey>
        where TKey : IEquatable<TKey>
    {
        public EnhancedSignInManager(
            UserManager<TUser, TKey> userManager, 
            IAuthenticationManager authenticationManager)
            : base(userManager, authenticationManager)
        {
        }
    
        public override async Task SignInAsync(
            TUser user, 
            bool isPersistent, 
            bool rememberBrowser)
        {
            var userIdentity = await CreateUserIdentityAsync(user).WithCurrentCulture();
    
            // Clear any partial cookies from external or two factor partial sign ins
            AuthenticationManager.SignOut(
                DefaultAuthenticationTypes.ExternalCookie, 
                DefaultAuthenticationTypes.TwoFactorCookie);
    
            if (rememberBrowser)
            {
                var rememberBrowserIdentity = AuthenticationManager
                    .CreateTwoFactorRememberBrowserIdentity(ConvertIdToString(user.Id));
    
                AuthenticationManager.SignIn(
                    new AuthenticationProperties { IsPersistent = isPersistent }, 
                    userIdentity, 
                    rememberBrowserIdentity);
            }
            else
            {
                AuthenticationManager.SignIn(
                    new AuthenticationProperties { IsPersistent = isPersistent }, 
                    userIdentity);
            }
        }
    
        private async Task<SignInStatus> SignInOrTwoFactor(TUser user, bool isPersistent)
        {
            var id = Convert.ToString(user.Id);
    
            if (UserManager.SupportsUserTwoFactor 
                && await UserManager.GetTwoFactorEnabledAsync(user.Id)
                                    .WithCurrentCulture()
                && (await UserManager.GetValidTwoFactorProvidersAsync(user.Id)
                                     .WithCurrentCulture()).Count > 0
                    && !await AuthenticationManager.TwoFactorBrowserRememberedAsync(id)
                                                   .WithCurrentCulture())
            {
                var identity = new ClaimsIdentity(
                    DefaultAuthenticationTypes.TwoFactorCookie);
    
                identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, id));
    
                AuthenticationManager.SignIn(identity);
    
                return SignInStatus.RequiresVerification;
            }
            await SignInAsync(user, isPersistent, false).WithCurrentCulture();
            return SignInStatus.Success;
        }
    
        public override async Task<SignInStatus> PasswordSignInAsync(
            string userName, 
            string password, 
            bool isPersistent, 
            bool shouldLockout)
        {
            if (UserManager == null)
            {
                return SignInStatus.Failure;
            }
    
            var user = await UserManager.FindByNameAsync(userName).WithCurrentCulture();
            if (user == null)
            {
                return SignInStatus.Failure;
            }
    
            if (UserManager.SupportsUserLockout 
                && await UserManager.IsLockedOutAsync(user.Id).WithCurrentCulture())
            {
                return SignInStatus.LockedOut;
            }
    
            if (UserManager.SupportsUserPassword 
                && await UserManager.CheckPasswordAsync(user, password)
                                    .WithCurrentCulture())
            {
                return await SignInOrTwoFactor(user, isPersistent).WithCurrentCulture();
            }
            if (shouldLockout && UserManager.SupportsUserLockout)
            {
                // If lockout is requested, increment access failed count
                // which might lock out the user
                await UserManager.AccessFailedAsync(user.Id).WithCurrentCulture();
                if (await UserManager.IsLockedOutAsync(user.Id).WithCurrentCulture())
                {
                    return SignInStatus.LockedOut;
                }
            }
            return SignInStatus.Failure;
        }
    }
    

    I hope it helps. Cheers

    0 讨论(0)
提交回复
热议问题