Ich bin neu bei der ASP.NET-Identität und versuche immer noch, mich mit der Funktionsweise zu beschäftigen. Leider habe ich festgestellt, dass viele der Tutorials, die ich ausprobiert habe, für Identity 1.0 sind, während ich versuche, mit Identity 2.0 zu arbeiten.
Das größte Problem, dem ich gegenüberstehe, ist etwas, von dem ich dachte, dass es einfach wäre, aber es hat sich herausgestellt, dass es nicht so ist. Ich versuche, eine vorhandene Datenbank mit einer vorhandenen Benutzertabelle zu verwenden. Derzeit kann ich scheinbar nur Identity erstellen, um eigene Tabellen zum Speichern von Benutzerdaten zu erstellen. Ich möchte Entity Framework nicht verwenden, aber ich hatte große Schwierigkeiten, Entity Framework von Identity 2.0 zu trennen.
In meiner Situation benutze ich SQL Server. Ich dachte, ich würde versuchen, den benutzerdefinierten Provider für MySQL unter diesem Link zu implementieren: http://www.asp.net/identity/overview/extensibility/implementing-a-custom -mysql-aspnet-identity-storage-provider und https://github.com/raquelsa/AspNet.Identity.MySQL . Dies scheint nur unter Identität 1 zu funktionieren. Es scheint einen neueren zu geben, der Entity Framework verwendet. Ich habe auch versucht, https://github.com/ILMServices/RavenDB.AspNet.Identity .
Bei allem, was ich ausprobiert habe, bleibe ich bei folgender Zeile stecken:
var manager = new IdentityUserManager(new UserStore<IdentityUser>(context.Get<ApplicationDbContext>()));
Das Problem, mit dem ich konfrontiert bin, ist, dass ich die ApplicaitonDbContext-Klasse gemäß den Anweisungen für RavenDB entfernen muss. Allerdings weiß ich nicht, was ich stattdessen in diese Zeile schreiben soll.
Die Fehler die ich bekomme sind:
Der nicht generische Typ 'AspNet.Identity.MySQL.UserStore' kann nicht mit Typargumenten verwendet werden
und
Der Typ- oder Namespace-Name 'ApplicationDbContext' konnte nicht gefunden werden (fehlt eine using-Direktive oder eine Assemblyreferenz?)
Der zweite Fehler ist zu erwarten, jedoch bin ich nicht sicher, was in dieser Codezeile verwendet werden soll. Hat jemand Erfahrung mit der Implementierung eines benutzerdefinierten Providers ohne Entity Framework?
Vielen Dank.
Update 1:
Ich habe folgendes Tutorial [ http://aspnetguru.com/customize-authentication-to-your-own-set-of-tables-in-asp-net-mvc-5/ ] versucht, aber es erscheint Unvollständig sein, mit Kompilierungs- oder Laufzeitfehlern, wenn das Tutorial genau befolgt wird Ein paar Probleme habe ich noch ...
Beim Ersetzen aller Instanzen von "ApplicationUser" durch "User" treten Probleme mit der folgenden Zeile in IdentityConfig.cs auf
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<MyDbContext>()));
Das Ändern von ApplicationUser in User verursacht den folgenden Fehler
Der Typ 'WebApplicationTest2.Models.User' kann nicht als Typparameter 'TUser' im generischen Typ oder der generischen Methode 'Microsoft.AspNet.Identity.EntityFramework.UserStore' verwendet werden. Es findet keine implizite Referenzkonvertierung von 'WebApplicationTest2.Models.User' in 'Microsoft.AspNet.Identity.EntityFramework.IdentityUser' statt.
Ich habe auch Schwierigkeiten, den Benutzermanager und viele der ASync-Methoden zu verwenden. Die folgenden Zeilen funktionieren nicht:
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));
In AccountController.cs mit den folgenden Fehlern:
Die beste überladene Methode für "Microsoft.Owin.Security.IAuthenticationManager.SignIn (Microsoft.Owin.Security.AuthenticationProperties, params System.Security.Claims.ClaimsClaimsIdentity [])" enthält einige ungültige Argumente.
'WebApplicationTest2.Models.User' enthält keine Definition für 'GenerateUserIdentityAsync' und keine Erweiterungsmethode 'GenerateUserIdentityAsync', die ein erstes Argument des Typs 'WebApplicationTest2.Models.User' akzeptiert (fehlt eine using-Direktive oder eine Assemblyreferenz) ?)
In Ihren Beispielen möchten Sie die Variable DbContext
durch etwas anderes ersetzen. Ich glaube jedoch, dass Sie Ihre Bemühungen um eine Stufe höher konzentrieren müssen.
Das Framework hat eine Klasse UserManager
, die dafür verantwortlich ist, die Benutzer und die zugehörigen Informationen zu verwalten, jedoch nicht zu speichern. Wenn die Benutzer (oder die zugehörigen Informationen) gespeichert werden sollen, wird standardmäßig der bereitgestellte UserStore<IdentityUser>
verwendet, der weiß, wie IdentityUser
-Instanzen mithilfe einer DbContext
in einer Datenbank gespeichert werden.
Im 2.0-Framework wurden die verschiedenen Bits des Identitätsspeichers in mehrere Schnittstellen aufgeteilt. Die Standardimplementierung UserStore<IdentityUser>
implementiert mehrere dieser Schnittstellen und speichert die Daten für alle in der Datenbank mithilfe einer DBContext
.
Wenn Sie sich die Definition des standardmäßig bereitgestellten, auf Entity Framework basierenden UserStore ansehen, werden Sie feststellen, dass viele dieser kleinen Schnittstellen implementiert werden:
public class UserStore<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> : IUserLoginStore<TUser, TKey>,
IUserClaimStore<TUser, TKey>, IUserRoleStore<TUser, TKey>, IUserPasswordStore<TUser, TKey>,
IUserSecurityStampStore<TUser, TKey>, IQueryableUserStore<TUser, TKey>, IUserEmailStore<TUser, TKey>,
IUserPhoneNumberStore<TUser, TKey>, IUserTwoFactorStore<TUser, TKey>, IUserLockoutStore<TUser, TKey>,
IUserStore<TUser, TKey>, IDisposable
where TUser : IdentityUser<TKey, TUserLogin, TUserRole, TUserClaim>
where TRole : IdentityRole<TKey, TUserRole>
where TKey : Object, IEquatable<TKey>
where TUserLogin : new(), IdentityUserLogin<TKey>
where TUserRole : new(), IdentityUserRole<TKey>
where TUserClaim : new(), IdentityUserClaim<TKey>
Da Sie Entity Framework überhaupt nicht verwenden möchten, müssen Sie eigene Implementierungen einiger dieser wichtigen Schnittstellen bereitstellen, die diese Daten an den Stellen speichern, an denen die Daten gespeichert werden sollen. Die Hauptschnittstelle ist IUserStore<Tuser,TKey>
. Dies definiert den Vertrag zum Speichern von Benutzern, die einen Schlüssel eines bestimmten Typs haben. Wenn Sie nur Benutzer und keine anderen Informationen speichern möchten, können Sie diese Schnittstelle implementieren und Ihre Implementierung dann an die Variable UserManager
übergeben, und Sie sollten bereit sein.
Es ist unwahrscheinlich, dass dies ausreicht. Wahrscheinlich möchten Sie Passwörter, Rollen, Anmeldungen usw. für Ihre Benutzer. Wenn ja, müssen Sie Ihre Klasse erstellen, die IUserStore<Tuser,TKey>
implementiert, und außerdem IUserPasswordStore<TUser, TKey>
, IRoleStore<TRole, TKey>
und IUserClaimStore<TUser, TKey>
implementieren.
Eine Liste aller Schnittstellen auf MSDN finden Sie hier
Abhängig von den Bits, die Sie verwenden möchten, müssen Sie diese Schnittstellen implementieren.
Sie müssen wahrscheinlich auch Ihre eigenen Versionen der Identity*
-Klassen definieren, die für das Entity-Framework bereits vorhanden sind . Sie benötigen also eine eigene IdentityUser
-Klasse, die die Benutzer enthält, die Sie speichern möchten, und IdentityUserClaim
für die Benutzeransprüche. Ich habe das nicht selbst gemacht, also bin ich nicht ganz sicher, aber ich habe das Gefühl, dass Sie das tun müssen.
Scott Allen hat einen guten Artikel über die verschiedenen Teile des Modells, der nützlich sein könnte.
Ihre Probleme mit dieser Zeile:
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));
Es gibt eine Methode namens GenerateUserIdentityAsync
, die für Applicationuser
definiert ist und die IdentityUser
erweitert. Es ist in dem Vorlagenprojekt definiert, das ich glaube, und sieht ungefähr so aus:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
UserManager<ApplicationUser> manager) {
// Note the authenticationType must match the one
// defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity =
await manager.CreateIdentityAsync(this,
DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
Da Sie das Entity-Framework IdentityUser
nicht mehr verwenden, müssen Sie entweder eine ähnliche Methode oder Ihre eigene User
-Klasse definieren oder die gleiche Funktionalität auf andere Weise implementieren (z. B. stattdessen await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie)
aufrufen).
Ich bin für Identity selbst ziemlich neu. Implementiert Ihre Benutzerentität die IUser-Schnittstelle? z.B.
public partial class User : IUser<Guid> //Whatever your key is
{
public Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
{
return Task.FromResult(GenerateUserIdentity(manager));
}
public ClaimsIdentity GenerateUserIdentity(ApplicationUserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = manager.CreateIdentity<User, Guid>(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
Dann können Sie sich anmelden, um sich anzumelden:
public async Task SignInAsync(User user, bool isPersistent)
{
var userIdentity = await user.GenerateUserIdentityAsync(UserManager);
AuthenticationManager.SignIn(
new AuthenticationProperties
{
IsPersistent = isPersistent
},
userIdentity
);
}
Ich denke, dass dies kürzlich in ApplicationUser
aktualisiert wurde:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
Es heißt so von AccountController
-> GetExternalLogin
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
CookieAuthenticationDefaults.AuthenticationType);