web-dev-qa-db-de.com

Identität 2.0 mit beachierten Tabellen

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) ?)

29
joshhendo

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).

37
Sam Holder

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

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);
1
Ogglas