So erstellen Sie einen Identitätsbenutzer basierend auf Ansprüchen prinicpals [Duplikat]

Nov 24 2020

Ich verwende asp.net mvc mit der Authentifizierung von Arbeits- / Schulkonten. Derzeit versuche ich, Identität in den Benutzerprozess zu implementieren.

Hier ist meine ApplicationUserKlasse:

public class ApplicationUser: IdentityUser
{
    public ICollection<Semester> Semesters { get; set; }
}

Bisher funktioniert Identität einwandfrei, es gibt nur ein Problem. Wenn ich mich mit meinem Schulkonto bei der App anmelde, kann ich das ClaimsPrincipalswie Userin den Controllern aufrufen . Um den aktuellen Stand zu erhalten ApplicationUser, können Sie das UserManager( await _userManager.GetUserAsync(User)mit Userdem ClaimsPrincipals) verwenden. Da ich mein Schulkonto jedoch nicht in der Datenbank gespeichert habe, ist das Ergebnis null. Wenn ich eine neue ApplicationUserwie folgt erstelle

var newUser = new ApplicationUser()
{
    UserName = User.Identity.Name,
    Email = User.Identity.Name
};
await _userManager.CreateAsync(newUser);
await _userManager.AddClaimsAsync(newUser, User.Claims);

Dadurch wird der neue Benutzer mit den Ansprüchen erfolgreich erstellt und in der Datenbank gespeichert. Aber dann, wenn ich versuche, das neue ApplicationUsermit await _userManager.GetUserAsync(User)dem Ergebnis zu erstellen, wird immer noch null sein. Wenn ich auf meine zugreife DbContextund alles bekomme ApplicationUsers, ist das neu erstellte ApplicationUserda. Wie kann ich eine ApplicationUserbasierend auf dem ClaimsPrincipalsLogin meines Schulkontos erstellen ?

Antworten

Ogglas Dec 07 2020 at 19:49

Dank an @poke dafür.

UserManager.GetUserAsyncWird intern verwendet UserManager.GetUserId, um die Benutzer-ID des Benutzers abzurufen, die dann zum Abfragen des Objekts aus dem Benutzerspeicher (dh Ihrer Datenbank) verwendet wird.

GetUserId sieht im Grunde so aus:

public string GetUserId(ClaimsPrincipal principal)
{
    return principal.FindFirstValue(Options.ClaimsIdentity.UserIdClaimType);
}

Dies gibt also den Anspruchswert von zurück Options.ClaimsIdentity.UserIdClaimType. Optionsist das IdentityOptionsObjekt , mit dem Sie Identität konfigurieren. Standardmäßig ist der Wert von UserIdClaimTypeIS ClaimTypes.NameIdentifier, dh "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".

Wenn Sie also versuchen zu verwenden UserManager.GetUserAsync(HttpContext.User), wo dieser Benutzerprinzipal einen UserIDAnspruch hat, sucht der Benutzermanager einfach nach einem anderen Anspruch.

Sie können dies beheben, indem Sie entweder auf Folgendes umschalten ClaimTypes.NameIdentifier:

new ClaimsIdentity(new[]
{
    new Claim(ClaimTypes.Name, user.UserName),
    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
})

Oder Sie konfigurieren Identität ordnungsgemäß, sodass Ihr UserIDAnspruchstyp verwendet wird:

// in Startup.ConfigureServices
services.AddIdentity(options => {
    options.ClaimIdentity.UserIdClaimType = "UserID";
});

Quelle:

https://stackoverflow.com/a/51122850/3850405

MattE. Dec 04 2020 at 05:55

Die Ansprüche eines externen Anbieters sind spezifisch für diesen Anbieter. Es meldet sich nicht beim lokalen Identitätsspeicher in Ihrer App an, sondern behauptet nur zu wissen, wer der Benutzer ist. Sie müssen den Benutzer also in Ihrem Geschäft (SignInManager) anmelden, bevor Sie ihn für die Autorisierung verwenden können. Wenn Sie sich nicht für den Schutz von Ressourcen interessieren und nur den Benutzer kennen möchten, können Sie ihn direkt Ihrem internen Geschäft zuordnen

Die Ansprüche im Header müssen von der ASPNET-Middleware mithilfe eines Authentifizierungsanbieters abgefangen werden, der dann das Benutzerobjekt im HttpContext festlegt. Sobald Sie den Benutzer haben, müssen Sie Ihren lokalen Benutzerspeicher denen aus dem Schulkonto zuordnen und dann die Ansprüche als separaten Anruf vom Ergebnis erhalten. Normalerweise ist die E-Mail der Betreff und kann für die Zuordnung verwendet werden:

    var userName = User.Identity.Name;
    var user = _userManager.FindByNameAsync(userName);
    var claims = _userManager.GetClaimsAsync(user);