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ć IUserStore
implementation. 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.
'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
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
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