2015-06-14 14 views
5

Tutte le procedure di autenticazione e autorizzazione della mia app vengono eseguite utilizzando stored procedure. Ho scritto una lezione con tutte le funzionalità di cui ho bisogno, ad es. GetUsers, Login, AddRole, AddMember, ecc. Anche la pagina di amministrazione per la gestione di utenti e ruoli e permessi viene eseguita utilizzando questa classe.Implementazione di UserManager per utilizzare una classe personalizzata e stored procedure

Ho solo bisogno di aggiungere authentication (intendo l'attributo authorize), i cookie per Login e Logout e memorizzare alcuni dati lato server per ogni accesso. Penso di aver bisogno di implementare Identity per quello?

In tal caso, puoi indicarmi la sua implementazione? Sembra che la cosa fondamentale da fare sia implementare un metodo create che passa un'istanza di IUserStore al costruttore. Ma non ho bisogno di avere tabelle per utenti o ruoli, come posso implementare questo metodo?

Questa è la classe corrente e, per favore, fatemi sapere se è necessario vedere la mia classe di autenticazione personalizzata che utilizza stored procedure.

public class AppUserManager : UserManager<AppUser> 
{ 
    public AppUserManager(IUserStore<AppUser> store) : base(store) { } 
    public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context) 
    { 
     //AppUserManager manager = new AppUserManager(); 
     //return manager; 
     return null; 
    } 
} 

risposta

7

Come alisabzevari suggerito è necessario implementare il IUserStore.
Non si dipende nemmeno dalla memoria e dalla struttura della tabella definita. È possibile personalizzare ogni singolo bit del livello di archiviazione.

ho fatto alcuni esperimenti e cercato di attuare il mio UserManager e RoleManager utilizzando un deposito diverso, come ad esempio Biggy: a base di File

Un Documento Store per .NET.

È possibile trovare il codice here su GitHub.

prima cosa da fare è quello di attuare il vostro UserManager cui è possibile configurare i requisiti per la convalida della password:

public class AppUserManager : UserManager<AppUser, int> 
{ 
    public AppUserManager (IUserStore<AppUser, int> store): base(store) 
    { 
     this.UserLockoutEnabledByDefault = false; 
     // this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10); 
     // this.MaxFailedAccessAttemptsBeforeLockout = 10; 
     this.UserValidator = new UserValidator<User, int>(this) 
     { 
     AllowOnlyAlphanumericUserNames = false, 
     RequireUniqueEmail = false 
     }; 

     // Configure validation logic for passwords 
     this.PasswordValidator = new PasswordValidator 
     { 
     RequiredLength = 4, 
     RequireNonLetterOrDigit = false, 
     RequireDigit = false, 
     RequireLowercase = false, 
     RequireUppercase = false, 
     }; 
    } 
} 

e quindi definire il vostro IUserStoreimplementation. Il metodo principale è necessario implementare è CreateAsync:

public System.Threading.Tasks.Task CreateAsync(User user) 
{ 
    // Saves the user in your storage. 
    return Task.FromResult(user); 
} 

riceverà un IUser che si deve persistere nel vostro storage personalizzato e restituirlo.

Se si dispone di uno sguardo al codice che ho implemented potete vedere ho usato un paio di interfacce IUserRoleStore, IUserPasswordStore, IUserClaimStore ecc ecc come ho bisogno di utilizzare i ruoli e reclami.

Ho implementato anche il mio ownSignInManager.

Dopo aver definito tutto l'implementazione è possibile il bootstrap tutto a startup:

app.CreatePerOwinContext<Custom.Identity.UserManager>(() => new Custom.Identity.UserManager(new Custom.Identity.UserStore(folderStorage))); 
app.CreatePerOwinContext<Custom.Identity.RoleManager>(() => new Custom.Identity.RoleManager(new Custom.Identity.RoleStore(folderStorage))); 
app.CreatePerOwinContext<Custom.Identity.SignInService>((options, context) => new Custom.Identity.SignInService(context.GetUserManager<Custom.Identity.UserManager>(), context.Authentication)); 

È possibile controllare il mio AccountController dove cerco di convalidare l'utente:

var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false); 
switch (result) 
{ 
case SignInStatus.Success: 
    return RedirectToLocal(returnUrl); 
case SignInStatus.LockedOut: 
    return View("Lockout"); 
case SignInStatus.RequiresVerification: 
    return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); 
case SignInStatus.Failure: 
default: 
    ModelState.AddModelError("", "Invalid login attempt."); 
    return View(model); 
} 

volta PasswordSignInAsync si chiama noterai alcuni dei metodi del tuo UserManager chiamati. Il primo sarà FindByNameAsync:

public System.Threading.Tasks.Task<User> FindByNameAsync(string userName) 
{ 
    //Fetch your user using the username. 
    return Task.FromResult(user); 
} 

Si dovrà implementare la stored procedure, immagino, dove potrete prendere il vostro utente dal DB.

Poi un altro metodo FindByIdAsync sarà called:

public System.Threading.Tasks.Task<User> FindByIdAsync(int userId) 
{ 
    // Fetch - again - your user from the DB with the Id. 
    return Task.FromResult(user); 
} 

Anche in questo caso si dovrà utilizzare la stored procedure per trovare l'utente con la sua/il suo id.

Se si scarica il mio progetto da github e si gioca con esso, si noterà che molti di questi metodi verranno chiamati più volte. Non avere paura È così che va.

Vorrei suggerire di inserire punti di interruzione in ogni singolo metodo di UserStore e vedere come tutto si combina.

+0

'L'input non è una stringa Base-64 valida poiché contiene un carattere non di base 64, più di due caratteri di riempimento o un carattere non valido tra i caratteri di riempimento. Per il login e in' UserManager.FindAsync' Ottengo l'errore sopra riportato. Qualche idea? Penso che sia relativo a 'GetPasswordHashAsync'. Cosa posso fare per quello? – Akbari

+1

È difficile dirlo. Hai provato il mio progetto di esempio? FindAsync utilizza UserLoginInfo. Passa attraverso quella pipe se stai usando un provider esterno (google, facebook). Se non lo usi dovresti passare lì. Nel caso in cui si stia utilizzando un provider esterno è possibile implementare il gestore UserLoginInfo. È possibile controllare [implementazione] di Raven (https://github.com/ILMServices/RavenDB.AspNet.Identity/blob/master/RavenDB.AspNet.Identity/UserStore.cs#L134). – LeftyX

+0

Grazie Lefty, ho controllato il tuo codice. Non sto usando provider esterni. E invece di usare Trova gestore utenti, ho usato la mia funzione personalizzata per risparmiare tempo! :) – Akbari

4

È necessario implementare l'interfaccia IUserStore. Vedere this article per informazioni su come implementare i provider di archiviazione personalizzati per l'identità ASP.NET.

1

È anche possibile eseguire l'override dei metodi nella classe UserManager (ad esempio ApplicationUserManager) per gestire l'autorizzazione. Ecco un esempio che utilizza la logica personalizzata UserManager.FindAsync. La classe UserManager viene utilizzata dalla classe ApplicationOAuthProvider durante l'autenticazione.

public class ApplicationUserManager : UserManager<ApplicationUser> 
{ 
    public ApplicationUserManager() : base(new EmptyUserStore()) { } 

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    { 
     return new ApplicationUserManager(); 
    } 

    public override Task<ApplicationUser> FindAsync(string userName, string password) 
    { 
     // Authentication logic here. 
     throw new NotImplementedException("Authenticate userName and password"); 

     var result = new ApplicationUser { UserName = userName }; 
     return Task.FromResult(result); 
    } 
} 

/// <summary> 
/// User Store with no implementation. Required for UserManager. 
/// </summary> 
internal class EmptyUserStore : IUserStore<ApplicationUser> 
{ 
    public Task CreateAsync(ApplicationUser user) 
    { 
     throw new NotImplementedException(); 
    } 

    public Task DeleteAsync(ApplicationUser user) 
    { 
     throw new NotImplementedException(); 
    } 

    public Task<ApplicationUser> FindByIdAsync(string userId) 
    { 
     throw new NotImplementedException(); 
    } 

    public Task<ApplicationUser> FindByNameAsync(string userName) 
    { 
     throw new NotImplementedException(); 
    } 

    public Task UpdateAsync(ApplicationUser user) 
    { 
     throw new NotImplementedException(); 
    } 

    public void Dispose() 
    { 
     // throw new NotImplementedException(); 
    } 
} 

Si noti che questa implementazione non utilizza i vantaggi dell'interfaccia IUserStore.

Problemi correlati