ASP.NET Identität ist ein wenig übermäßig komplex, würde ich sagen.
Im August 2014 haben sie die neue Version 2.1 angekündigt und die Dinge haben sich wieder geändert.
Zunächst einmal lassen Sie uns von EntityFramework
loszuwerden:
public class User: IUser<int>
{
public User()
{
this.Roles = new List<string>();
this.Claims = new List<UserClaim>();
}
public User(string userName)
: this()
{
this.UserName = userName;
}
public User(int id, string userName): this()
{
this.Id = Id;
this.UserName = userName;
}
public int Id { get; set; }
public string UserName { get; set; }
public string PasswordHash { get; set; }
public bool LockoutEnabled { get; set; }
public DateTime? LockoutEndDateUtc { get; set; }
public bool TwoFactorEnabled { get; set; }
public IList<string> Roles { get; private set; }
public IList<UserClaim> Claims { get; private set; }
}
Wie können Sie:
Uninstall-Package Microsoft.AspNet.Identity.EntityFramework
Jetzt haben wir unsere eigene Definition von User
Implementierung der Schnittstelle IUser
(Microsoft.AspNet.Identity) implementieren siehe Ich habe den Typ meines Id
(int) definiert.
Dann müssen Sie Ihre benutzerdefinierte UserManager
erben von Microsoft.AspNet.Identity.UserManager
unter Angabe Ihrer Benutzer-Typ und der Schlüssel-Typ definieren.
public class UserManager : UserManager<User, int>
{
public UserManager(IUserStore<User, 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,
};
}
}
Ich habe meine Validierungsregeln hier implementiert, aber Sie können es draußen behalten, wenn Sie bevorzugen.
UserManager
benötigt einen UserStore
(IUserStore).
Hier definieren Sie Ihre DB-Logik. Es gibt einige zu implementierende Schnittstellen. Nicht alle sind jedoch obligatorisch.
public class UserStore :
IUserStore<User, int>,
IUserPasswordStore<User, int>,
IUserLockoutStore<User, int>,
IUserTwoFactorStore<User, int>,
IUserRoleStore<User, int>,
IUserClaimStore<User, int>
{
// You can inject connection string or db session
public UserStore()
{
}
}
Ich habe nicht alle Methoden für jede Schnittstelle enthalten. Sobald Sie getan haben, dass Sie in der Lage sein werden, den neuen Benutzer zu schreiben:
public System.Threading.Tasks.Task CreateAsync(User user)
{
}
es durch Id holen:
public System.Threading.Tasks.Task<User> FindByIdAsync(int userId)
{
}
und so weiter.
Dann müssen Sie Ihre SignInManager
erben von Microsoft.AspNet.Identity.Owin.SignInManager
definieren.
public class SignInManager: SignInManager<User, int>
{
public SignInManager(UserManager userManager, IAuthenticationManager authenticationManager): base(userManager, authenticationManager)
{
}
public override Task SignInAsync(User user, bool isPersistent, bool rememberBrowser)
{
return base.SignInAsync(user, isPersistent, rememberBrowser);
}
}
Ich habe nur SignInAsync
umgesetzt: es wird erzeugt ein ClaimsIdentity.
Das ist es ziemlich viel.
Jetzt in Ihrer Startup
Klasse müssen Sie Owin
, wie Sie die UserManager
und die SignInManager
erstellen.
app.CreatePerOwinContext<Custom.Identity.UserManager>(() => new Custom.Identity.UserManager(new Custom.Identity.UserStore()));
// app.CreatePerOwinContext<Custom.Identity.RoleManager>(() => new Custom.Identity.RoleManager(new Custom.Identity.RoleStore()));
app.CreatePerOwinContext<Custom.Identity.SignInService>((options, context) => new Custom.Identity.SignInService(context.GetUserManager<Custom.Identity.UserManager>(), context.Authentication));
Ich habe nicht die Fabriken verwendet, um Sie in der Standardvorlage Ursache finden wollte ich wie möglich die Dinge so einfach zu halten.
Und aktivieren Sie Ihre Anwendung das Cookie zu verwenden:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<Custom.Identity.UserManager, Custom.Identity.User, int>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentityCallback: (manager, user) =>
{
var userIdentity = manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
return (userIdentity);
},
getUserIdCallback: (id) => (Int32.Parse(id.GetUserId()))
)}
});
Jetzt in Ihrem Konto Controller - oder den Controller verantwortlich für die Login - Sie erhalten die UserManager
und die SignInManager
bekommen müssen:
public Custom.Identity.SignInManager SignInManager
{
get
{
return HttpContext.GetOwinContext().Get<Custom.Identity.SignInManager>();
}
}
public Custom.Identity.UserManager UserManager
{
get
{
return HttpContext.GetOwinContext().GetUserManager<Custom.Identity.UserManager>();
}
}
Sie die SignInManager
für die Anmeldung verwenden:
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
und die UserManager
den Benutzer zu erstellen, fügen Sie Rollen und Ansprüche:
if (ModelState.IsValid)
{
var user = new Custom.Identity.User() { UserName = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// await UserManager.AddToRoleAsync(user.Id, "Administrators");
// await UserManager.AddClaimAsync(user.Id, new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Country, "England"));
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
Es scheint kompliziert ... und es ist ... Art. Wenn Sie mehr darüber lesen möchten, gibt es eine gute Erklärung here und here.
Wenn Sie etwas Code ausführen und sehen möchten, wie es funktioniert, habe ich einige code zusammengestellt, die mit Biggy arbeitet (wie ich nicht zu viel Zeit verlieren wollte, um Tabellen und solche Sachen zu definieren).
Wenn Sie die Möglichkeit haben, meinen Code aus dem Github Repo herunterzuladen, werden Sie feststellen, dass ich ein sekundäres Projekt (Custom.Identity) erstellt habe, wo ich alle meine ASP.NET Identity Zeug gehalten habe.
Die einzige nuget Pakete, die Sie es benötigen, sind:
- Microsoft.AspNet.Identity.Core
- Microsoft.AspNet.Identity.Owin
Ja, Sie können anpassen, wie die UserManager verhält sich. Die Art und Weise, wie es seine Daten erhält, ist durch die Implementierung des 'IUserStore'. Hier ist eine Antwort, die Ihnen bei der Anpassung helfen kann. http://stackoverflow.com/questions/19940014/asp-net-identity-with-ef-database-first-mvc5/21122865#21122865 – Shoe