2014-08-28 8 views
17

Uygulamam için bir özel IUserStore<TUser,int> oluşturdum. İhtiyacım arabirimleri,Özel ASP.NET Kimlik 2.0 KullanıcıStore - Gerekli tüm arayüzleri uyguluyor mu?

IUserStore<TUser, int>, 
    IUserRoleStore<TUser, int>, 
    IUserLockoutStore<TUser, int>, 
    IUserPasswordStore<TUser, int> 

uyguladık ama

var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false); 

demenden

Store does not implement IUserTwoFactorStore<TUser>. 

ben her yerde iki faktörlü kimlik doğrulamasını kullanarak değilim diyerek istisna olsun benim uygulama. Neden bu arayüzü uygulamaya koymamı bekliyor? Bunları kullanmasam bile, tüm bu arayüzleri uygulamak zorunda mıyım?

cevap

14

Aynı problem vardı. Şu an için, SignInManager.SignInOrTwoFactor yöntemi GetTwoFactorAuthentication için körü körüne denetlediğinden, UserStore IUserTwoFactorStore'u uygulamadığı zaman bir istisna atar.

Microsoft'un SignInManager PasswordSignInAsync yönteminin özel bir SignInManager sınıfında geçersiz kılınması gerektiğine inanıyorum. Maalesef, işaret eden herhangi bir doküman veya numune bulamadım. Ben yardımcı olur umarım

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; 
    } 
} 

:

İşte bu sorunu çözmek için uygulanan SignInManager sarıcı sınıftır.

.... 
public Task<bool> GetTwoFactorEnabledAsync(User user) 
{ 
    return Task.FromResult(false); 
} 

public Task SetTwoFactorEnabledAsync(User user, bool enabled) 
{ 
    throw new NotImplementedException(); 
} 

Çalışıyor, sadece birkaç dakika önce yaptım rağmen ve: Cheers

+0

Teşekkürler, şimdiki engel üzerinde bana yardımcı oldu. – Andez

+4

Bu tam olarak ihtiyacım olan şey değil, ama bu bana doğru yolda işaret etti. Yönetici olmalıyım, Identity'nin mevcut veritabanımla çalışmasını sağlamak için bir kaç saatimi harcamak zorunda kaldığım için çok sinirlendim. –

+1

Bu hatayı alıyorum: 'System.Threading.Tasks.Task', 'WithCurrentCulture' için bir tanım içermiyor. Bir şey mi kaçırdım? Görünüşe göre doğrular. – fcaldera

15

Aslında IUserTwoFactorStore arayüzü gerçekten basit, şimdiye kadar benim uygulaması (ben yetkilendirme ya iki faktör kullanmayın) Bu mesafesindedir tüm uygulamayı iyice test etmedi.

+9

Evet, işe yarayacak, ama oldukça iğrenç. Liskov ikame prensibini öldürür. IUserTwoFactorStore uygulamasının denetlenmemesinin Kimlik Yöneticisi sınıfındaki bir tasarım hatası olduğunu söylemenin güvenli olduğunu düşünüyorum. –

1

Aynı problemi yaşadım ve bunu uygulamadığımı söylemek için IUserTwoFactorStore<TUser, TKey>'u uygulamak istemiyorum. Ama ben de geri dönmek istemiyorum ve eğer onu uygulamak istediğimde (ki bunu yapacağımı tahmin ediyorum) etrafta dolaşmak istemiyorum. Bu yüzden bir geleceğe uyumlu (ve yeniden kullanılabilir) çözümü olacağını düşündükleri:

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); 
    } 
} 

(@ gjsduarte cevabı esinlenerek) Muhtemelen diğer Get[feature]EnabledAsync(TKey userId) yöntemleri için aynı yapmak için iyi bir fikir olacaktır.