2015-06-14 13 views
5

Wszystkie procesy uwierzytelniania i autoryzacji mojej aplikacji są wykonywane przy użyciu procedur przechowywanych. Napisałem zajęcia ze wszystkimi niezbędnymi funkcjami, np. GetUsers, Login, AddRole, AddMember, itp. Strona administracyjna do zarządzania użytkownikami oraz rolami i uprawnieniami odbywa się za pomocą tej klasy.Implementacja menedżera użytkowników UserManager do używania niestandardowej klasy i procedur przechowywanych

Po prostu muszę dodać authentication (mam na myśli ten atrybut authorize), pliki cookie do logowania i wylogowania i przechowywania niektórych danych po stronie serwera dla każdego logowania. Chyba muszę zaimplementować Identity?

W takim przypadku, proszę, poprowadzić mnie wraz z wdrożeniem? Wydaje się, że bardzo podstawową rzeczą, którą musisz zrobić, to zaimplementować metodę create, która przekazuje instancję IUserStore do konstruktora. Ale nie muszę mieć tabel dla użytkowników ani ról, jak mogę wdrożyć tę metodę?

To jest aktualna klasa i proszę dać mi znać, jeśli potrzebujesz zobaczyć moją niestandardową klasę uwierzytelniania, która używa procedur przechowywanych.

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

Odpowiedz

7

Zgodnie z sugestią alisabzevari musisz zaimplementować swoją IUserStore.
Nie musisz nawet polegać na zdefiniowanej strukturze pamięci i tabeli. Możesz dostosować każdy bit warstwy przechowywania.

zrobiłem kilka eksperymentów i starał się realizować mój własny UserManager i RoleManager używając innej pamięci masowej, takich jak Biggy:

oparty na plikach Document Store dla .NET.

Możesz znaleźć kod here na GitHub.

Pierwszą rzeczą do zrobienia jest, aby realizować swoje UserManager gdzie można skonfigurować wymagania dla zatwierdzenia hasłem:

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

a następnie zdefiniować IUserStoreimplementation. Główną metodą należy wdrożyć to CreateAsync:

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

będzie otrzymywać IUser które trzeba utrzymywać w niestandardowym przechowywania i odesłać go.

Jeśli spojrzeć na kod ja już implemented widać Użyłem kilka interfejsów IUserRoleStore, IUserPasswordStore, IUserClaimStore etc etc jak ja potrzebne do korzystania z ról i roszczeń.

Zaimplementowałam również mój ownSignInManager.

Po zdefiniowaniu wszystkich implementacji można Bootstrap wszystko co 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)); 

Można sprawdzić moje AccountController gdzie staram się potwierdzić użytkownikowi:

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

Po PasswordSignInAsync nazywa zauważysz, że kilka metod twojego UserManager zostanie wywołanych. Pierwszy z nich będzie FindByNameAsync:

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

Trzeba będzie wdrożyć procedurę przechowywaną, myślę, gdzie można przynieść swoją użytkownika z DB.

Następnie inna metoda FindByIdAsync będzie called:

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

Znowu będziesz musiał korzystać z procedury przechowywanej, aby znaleźć użytkownika przez jego/jej ID.

Po pobraniu mojego projektu z github i zabawie z nim zauważysz, że większość z tych metod będzie się nazywać wiele razy. Nie bój się. Tak to już jest.

Proponuję wstawić punkty przerwania w każdej pojedynczej metodzie UserStore i zobaczyć, jak wszystko pasuje do siebie.

+0

'Dane wejściowe nie są prawidłowym ciągiem Base-64, ponieważ zawiera on 64-literowy znak bazowy, więcej niż dwa znaki dopełniające lub niedozwolony znak wśród znaków dopełniających." Do logowania i do 'UserManager.FindAsync' Otrzymuję powyższy błąd. Dowolny pomysł? Myślę, że jest to względne w stosunku do 'GetPasswordHashAsync'. Co mogę dla tego zrobić? – Akbari

+1

Trudno powiedzieć. Czy próbowałeś mojego przykładowego projektu? FindAsync używa UserLoginInfo. Przechodzi przez tę rurę, jeśli korzystasz z zewnętrznego dostawcy (google, facebook). Jeśli nie używasz tego, powinieneś przejść tam. W przypadku korzystania z zewnętrznego dostawcy można zaimplementować menedżera UserLoginInfo. Możesz sprawdzić implementację Ravena (https://github.com/ILMServices/RavenDB.AspNet.Identity/blob/master/RavenDB.AspNet.Identity/UserStore.cs#L134). – LeftyX

+0

Dzięki Lefty, sprawdziłem twój kod. Nie korzystam z zewnętrznych dostawców. Zamiast używać Findera menedżera użytkownika użyłem swojej własnej funkcji, by zaoszczędzić trochę czasu! :) – Akbari

4

Musisz zaimplementować interfejs IUserStore. Aby dowiedzieć się, jak zaimplementować Dostawcy niestandardowych pamięci masowych dla tożsamości ASP.NET, zobacz artykuł this article.

1

Można również zastąpić metody z klasy UserManager (np. ApplicationUserManager) w celu zarządzania autoryzacją. Oto przykład, który wykorzystuje niestandardową logikę UserManager.FindAsync. Klasa UserManager jest używana przez klasę ApplicationOAuthProvider podczas uwierzytelniania.

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

Zauważ, że ta realizacja nie korzysta z dobrodziejstw interfejsu IUserStore.

Powiązane problemy