9

Ho esaminato la letteratura corrente ma non riesco a allenare esattamente come far funzionare il nuovo sistema IdentityStore con il proprio database.Come utilizzare la nuova MVC5 Autenticazione con database esistente

La tabella utente del mio database è denominata tblMember una classe di esempio di seguito.

public partial class tblMember 
{ 
    public int id { get; set; } 
    public string membership_id { get; set; } 
    public string password { get; set; } 
    ....other fields 
} 

attualmente gli utenti di login con la membership_id che è unico e poi utilizzare l'ID in tutto il sistema, che è la chiave primaria. Non riesco a utilizzare uno scenario del nome utente per l'accesso poiché non è abbastanza unico su questo sistema.

Con gli esempi che ho visto sembra che il sistema è progettato per me abbastanza malleabile, ma non posso attualmente allenamento come ottenere il login locale per utilizzare il mio tavolo tblmember per l'autenticazione tramite membership_id e poi avrò accesso al che gli utenti memorizzano i record da qualsiasi controller tramite la proprietà User.

http://blogs.msdn.com/b/webdev/archive/2013/07/03/understanding-owin-forms-authentication-in-mvc-5.aspx

risposta

4

Supponendo che si sta utilizzando EF, si dovrebbe essere in grado di fare qualcosa del genere:

public partial class tblMember : IUserSecret 
{ 
    public int id { get; set; } 
    public string membership_id { get; set; } 
    public string password { get; set; } 
    ....other fields 

    /// <summary> 
    /// Username 
    /// </summary> 
    string UserName { get { return membership_id; set { membership_id = value; } 

    /// <summary> 
    /// Opaque string to validate the user, i.e. password 
    /// </summary> 
    string Secret { get { return password; } set { password = value; } } 
} 

Fondamentalmente il negozio password locale è chiamata IUserSecretStore nel nuovo sistema. Si dovrebbe essere in grado di collegare il vostro tipo di entità al costruttore AccountController in questo modo supponendo che si implementato tutto correttamente:

public AccountController() 
    { 
     var db = new IdentityDbContext<User, UserClaim, tblMember, UserLogin, Role, UserRole>(); 
     StoreManager = new IdentityStoreManager(new IdentityStoreContext(db)); 
    } 

Nota la proprietà User conterrà affermazioni degli utenti, e la richiesta NameIdentifier sarà mappare l'IUser.Id proprietà nel sistema di identità. Questo non è direttamente legato a IUserSecret, che è solo un nome utente/archivio segreto. I modelli di sistema una password locale come un account di accesso locale con providerKey = nome utente e loginProvider = "Locale"

Edit: Aggiunta di un esempio di un utente personalizzato e

public class CustomUser : User { 
     public string CustomProperty { get; set; } 
    } 

    public class CustomUserContext : IdentityStoreContext { 
     public CustomUserContext(DbContext db) : base(db) { 
      Users = new UserStore<CustomUser>(db); 
     } 
    } 

    [TestMethod] 
    public async Task IdentityStoreManagerWithCustomUserTest() { 
     var db = new IdentityDbContext<CustomUser, UserClaim, UserSecret, UserLogin, Role, UserRole>(); 
     var manager = new IdentityStoreManager(new CustomUserContext(db)); 
     var user = new CustomUser() { UserName = "Custom", CustomProperty = "Foo" }; 
     string pwd = "password"; 
     UnitTestHelper.IsSuccess(await manager.CreateLocalUserAsync(user, pwd)); 
     Assert.IsTrue(await manager.ValidateLocalLoginAsync(user.UserName, pwd)); 
     CustomUser fetch = await manager.Context.Users.FindAsync(user.Id) as CustomUser; 
     Assert.IsNotNull(fetch); 
     Assert.AreEqual("Custom", fetch.UserName); 
     Assert.AreEqual("Foo", fetch.CustomProperty); 
    } 

EDIT # 2: C'è anche un bug nell'implementazione di IdentityAuthenticationmanager.GetUserClaims che sta trasmettendo all'utente invece di IUser, quindi gli utenti personalizzati che non si estendono dall'Utente non funzioneranno.

Ecco il codice che è possibile utilizzare per sovrascrivere:

internal const string IdentityProviderClaimType = "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider"; 
    internal const string DefaultIdentityProviderClaimValue = "ASP.NET Identity"; 

/// <summary> 
/// Return the claims for a user, which will contain the UserIdClaimType, UserNameClaimType, a claim representing each Role 
/// and any claims specified in the UserClaims 
/// </summary> 
public override async Task<IList<Claim>> GetUserIdentityClaims(string userId, IEnumerable<Claim> claims) { 
    List<Claim> newClaims = new List<Claim>(); 
    User user = await StoreManager.Context.Users.Find(userId) as IUser; 
    if (user != null) { 
     bool foundIdentityProviderClaim = false; 
     if (claims != null) { 
      // Strip out any existing name/nameid claims that may have already been set by external identities 
      foreach (var c in claims) { 
       if (!foundIdentityProviderClaim && c.Type == IdentityProviderClaimType) { 
        foundIdentityProviderClaim = true; 
       } 
       if (c.Type != ClaimTypes.Name && 
        c.Type != ClaimTypes.NameIdentifier) { 
        newClaims.Add(c); 
       } 
      } 
     } 
     newClaims.Add(new Claim(UserIdClaimType, userId, ClaimValueTypes.String, ClaimsIssuer)); 
     newClaims.Add(new Claim(UserNameClaimType, user.UserName, ClaimValueTypes.String, ClaimsIssuer)); 
     if (!foundIdentityProviderClaim) { 
      newClaims.Add(new Claim(IdentityProviderClaimType, DefaultIdentityProviderClaimValue, ClaimValueTypes.String, ClaimsIssuer)); 
     } 
     var roles = await StoreManager.Context.Roles.GetRolesForUser(userId); 
     foreach (string role in roles) { 
      newClaims.Add(new Claim(RoleClaimType, role, ClaimValueTypes.String, ClaimsIssuer)); 
     } 
     IEnumerable<IUserClaim> userClaims = await StoreManager.Context.UserClaims.GetUserClaims(userId); 
     foreach (IUserClaim uc in userClaims) { 
      newClaims.Add(new Claim(uc.ClaimType, uc.ClaimValue, ClaimValueTypes.String, ClaimsIssuer)); 
     } 
    } 
    return newClaims; 
} 
+0

La prego di fornire un esempio completo. Vorrei utilizzare la mia classe utente che esegue il mapping alla tabella Utenti. Sembra che non sia l'unico a cercare una soluzione: http://stackoverflow.com/questions/17399933/how-do-i-configure-the-users-context-table –

+0

Modificato la mia risposta per contenere un'abitudine Utente, probabilmente implementeresti IUser invece di estendere Utente, ma il resto del codice dovrebbe essere lo stesso –

+0

@Hao Kung, attualmente sono confuso su come implementarlo correttamente, apprezzo che sia ancora in versione beta ma non compare alcun dettaglio reale sulla personalizzazione e il collegamento al tuo database/archivio password, ci sono altri esempi/risorse di cui sei a conoscenza? – Tim

Problemi correlati