Wie aktualisiere ich einen Anspruch in ASP.NET Identity?

89

Ich verwende die OWIN-Authentifizierung für mein MVC5-Projekt. Das ist meinSignInAsync

 private async Task SignInAsync(ApplicationUser user, bool isPersistent)
        {
            var AccountNo = "101";
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
            identity.AddClaim(new Claim(ClaimTypes.UserData, AccountNo));
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent, RedirectUri="Account/Index"}, identity);
        }

Wie Sie sehen können, habe ich AccountNoin die Anspruchsliste aufgenommen.

Wie kann ich diesen Anspruch irgendwann in meiner Bewerbung aktualisieren? Bisher habe ich Folgendes:

 public string AccountNo
        {

            get
            {
                var CP = ClaimsPrincipal.Current.Identities.First();
                var Account= CP.Claims.FirstOrDefault(p => p.Type == ClaimTypes.UserData);
                return Account.Value;
            }
            set
            {
                var CP = ClaimsPrincipal.Current.Identities.First();
                var AccountNo= CP.Claims.FirstOrDefault(p => p.Type == ClaimTypes.UserData).Value;
                CP.RemoveClaim(new Claim(ClaimTypes.UserData,AccountNo));
                CP.AddClaim(new Claim(ClaimTypes.UserData, value));
            }

        }

Wenn ich versuche, den Anspruch zu entfernen, erhalte ich diese Ausnahme:

Der Anspruch " http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata : 101" konnte nicht entfernt werden. Es ist entweder nicht Teil dieser Identität oder es ist ein Anspruch des Auftraggebers, der diese Identität enthält. Beispielsweise besitzt der Principal den Anspruch, wenn er einen GenericPrincipal mit Rollen erstellt. Die Rollen werden durch die Identität verfügbar gemacht, die im Konstruktor übergeben wird, aber nicht tatsächlich der Identität gehört. Eine ähnliche Logik gibt es für einen RolePrincipal.

Könnte mir jemand helfen, herauszufinden, wie ich den Anspruch aktualisieren kann?

Irshu
quelle
Wenn Sie Benutzerinformationen in einem Anspruch speichern und den Anspruch aktualisieren möchten, können Sie nach Änderung der Benutzerinformationen Folgendes aufrufen SignInManager.SignInAsync, um den Wert des Anspruchs zu aktualisieren . Siehe diese Frage
Hooman Bahreini

Antworten:

118

Ich habe eine Erweiterungsmethode zum Hinzufügen / Aktualisieren / Lesen von Ansprüchen basierend auf einer bestimmten ClaimsIdentity erstellt

namespace Foobar.Common.Extensions
{
    public static class Extensions
    {
            public static void AddUpdateClaim(this IPrincipal currentPrincipal, string key, string value)
            {
                var identity = currentPrincipal.Identity as ClaimsIdentity;
                if (identity == null)
                    return;

                // check for existing claim and remove it
                var existingClaim = identity.FindFirst(key);
                if (existingClaim != null)
                    identity.RemoveClaim(existingClaim);

                // add new claim
                identity.AddClaim(new Claim(key, value));
                var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
                authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
            }

            public static string GetClaimValue(this IPrincipal currentPrincipal, string key)
            {
                var identity = currentPrincipal.Identity as ClaimsIdentity;
                if (identity == null)
                    return null;

                var claim = identity.Claims.FirstOrDefault(c => c.Type == key);
                return claim.Value;
            }
    }
}

und dann zu benutzen

using Foobar.Common.Extensions;

namespace Foobar.Web.Main.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            // add/updating claims
            User.AddUpdateClaim("key1", "value1");
            User.AddUpdateClaim("key2", "value2");
            User.AddUpdateClaim("key3", "value3");
        }

        public ActionResult Details()
        {
            // reading a claim
            var key2 = User.GetClaim("key2");           
        }
    }
}
Frank Fu
quelle
Schließlich. Ich hatte eine andere Lösung dafür und es schien zu funktionieren ... meistens. Aber letztendlich auf diese Methode umgestellt, da sie immer zu funktionieren scheint. Danke dir!
Saml
3
Hat jemand die gleiche Lösung für Asp.Net One Core?
Martín
Dies scheint nur für die aktuelle Anwendung zu funktionieren. Ich möchte das vom SSO-Server ausgegebene Cookie aktualisieren, damit auch andere Apps darauf zugreifen können. Irgendeine Idee wie? Danke
Wer auch immer
@Whoever Da das Cookie vom SSO-Server signiert ist, um anzuzeigen, dass es nicht manipuliert wurde (und daher vertrauenswürdig ist), wäre ich überrascht, wenn es eine Möglichkeit gäbe, dies zu erreichen, da es manipuliert werden würde.
Mog0
2
var Claim = identity.Claims.First (c => c.Type == key); return Claim.Value; sollte var Claim = Identity.Claims.FirstOrDefault sein (c => c.Type == key); Rückgabeanspruch? .Wert;
Liuhongbo
55

Sie können eine neue erstellen ClaimsIdentityund dann die Schadensaktualisierung mit einer solchen durchführen.

set {
    // get context of the authentication manager
    var authenticationManager = HttpContext.GetOwinContext().Authentication;

    // create a new identity from the old one
    var identity = new ClaimsIdentity(User.Identity);

    // update claim value
    identity.RemoveClaim(identity.FindFirst("AccountNo"));
    identity.AddClaim(new Claim("AccountNo", value));

    // tell the authentication manager to use this new identity
    authenticationManager.AuthenticationResponseGrant = 
        new AuthenticationResponseGrant(
            new ClaimsPrincipal(identity),
            new AuthenticationProperties { IsPersistent = true }
        );
}
Irshu
quelle
4
Sie können den Anspruch aktualisieren, müssen den Benutzer jedoch weiterhin mit der aktualisierten Identität ab- und abmelden.
user3210546
3
Nein, der Benutzer wird nicht abgemeldet. Wir aktualisieren nur das Cookie des Benutzers
Irshu,
5
Denken Sie daran, dass dies nur die Identität aktualisiert. Wenn Sie diese Ansprüche speichern und auf Anfrage automatisch laden möchten, muss der Benutzermanager sie ebenfalls entfernen und aktualisieren. Hat einige Zeit gedauert! :(
Dennis van der Stelt
3
Was ist, wenn ich überhaupt keine Cookies habe und nur accessToken verwende? In meinem Fall sind die Ansprüche bei der nächsten Anfrage dieselben wie vor der Änderung. Die einzige Möglichkeit, meine Ansprüche zu aktualisieren, besteht darin, den Benutzer abzumelden und ihn zu bitten, sich erneut anzumelden :-(
Nozim Turakulov
1
Dies scheint nur für die aktuelle Anwendung zu funktionieren. Ich möchte das vom SSO-Server ausgegebene Cookie aktualisieren, damit auch andere Apps darauf zugreifen können. Irgendeine Idee wie? Danke
Wer auch immer
18

Ein weiterer (asynchroner) Ansatz, bei dem UserManager und SigninManager von Identity verwendet werden, um die Änderung im Identity-Cookie widerzuspiegeln (und optional Ansprüche aus der DB-Tabelle AspNetUserClaims zu entfernen):

// Get User and a claims-based identity
ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
var Identity = new ClaimsIdentity(User.Identity);

// Remove existing claim and replace with a new value
await UserManager.RemoveClaimAsync(user.Id, Identity.FindFirst("AccountNo"));
await UserManager.AddClaimAsync(user.Id, new Claim("AccountNo", value));

// Re-Signin User to reflect the change in the Identity cookie
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

// [optional] remove claims from claims table dbo.AspNetUserClaims, if not needed
var userClaims = UserManager.GetClaims(user.Id);
if (userClaims.Any())
{
  foreach (var item in userClaims)
  {
    UserManager.RemoveClaim(user.Id, item);
  }
}
RickL
quelle
Der Anhaltspunkt hier war für mich, dies SignInAsync() nach dem Einrichten der Ansprüche zu tun .
H Hund
Vielen Dank für den Tipp zum Entfernen der Ansprüche aus der DB. Mir wurde klar, dass ich nach mir selbst aufräumen musste.
Uber Schnoz
12

Mit der neuesten Asp.Net-Identität mit .net Core 2.1 kann ich Benutzeransprüche mit der folgenden Logik aktualisieren.

  1. Registrieren Sie sich UserClaimsPrincipalFactoryso, dass jedes Mal, wenn SignInManagerder Benutzer singt, die Ansprüche erstellt werden.

    services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimService>();
  2. Implementieren Sie eine benutzerdefinierte UserClaimsPrincipalFactory<TUser, TRole>wie unten

    public class UserClaimService : UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole>
    {
        private readonly ApplicationDbContext _dbContext;
    
        public UserClaimService(ApplicationDbContext dbContext, UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
        {
            _dbContext = dbContext;
        }
    
        public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
        {
            var principal = await base.CreateAsync(user);
    
            // Get user claims from DB using dbContext
    
            // Add claims
            ((ClaimsIdentity)principal.Identity).AddClaim(new Claim("claimType", "some important claim value"));
    
            return principal;
        }
    }
  3. Wenn Sie später in Ihrer Anwendung etwas in der Datenbank ändern und dies Ihrem authentifizierten und angemeldeten Benutzer mitteilen möchten, wird dies in den folgenden Zeilen erreicht:

    var user = await _userManager.GetUserAsync(User);
    await _signInManager.RefreshSignInAsync(user);

Dadurch wird sichergestellt, dass der Benutzer aktuelle Informationen sehen kann, ohne sich erneut anmelden zu müssen. Ich habe dies kurz vor der Rückgabe des Ergebnisses in den Controller eingefügt, damit nach Abschluss des Vorgangs alles sicher aktualisiert wird.

Anstatt bestehende Ansprüche zu bearbeiten und Rennbedingungen für sichere Cookies usw. zu erstellen, melden Sie den Benutzer einfach stillschweigend an und aktualisieren den Status :)

Mahmut C.
quelle
Vielen Dank, mit dem gleichen Problem konfrontiert und diese Lösung funktioniert besser für die Aktualisierung der Ansprüche für einen signierten Benutzer.
Amya
Vielen Dank! Das gleiche Problem gab es auch in Net Core 3.1
Kevin Tran
7

Ich bekomme auch diese Ausnahme und habe die Dinge so geklärt

var identity = User.Identity as ClaimsIdentity;
var newIdentity = new ClaimsIdentity(identity.AuthenticationType, identity.NameClaimType, identity.RoleClaimType);
newIdentity.AddClaims(identity.Claims.Where(c => false == (c.Type == claim.Type && c.Value == claim.Value)));
// the claim has been removed, you can add it with a new value now if desired
AuthenticationManager.SignOut(identity.AuthenticationType);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, newIdentity);
IDisposable
quelle
4

Einige Antworten von hier wurden mit meinen Ergänzungen in der wiederverwendbaren ClaimsManager- Klasse zusammengefasst.

Ansprüche wurden fortgeführt, Benutzer-Cookie aktualisiert, Anmeldung aktualisiert.

Bitte beachten Sie, dass ApplicationUser durch IdentityUser ersetzt werden kann, wenn Sie den vorherigen nicht angepasst haben. Auch in meinem Fall muss die Logik in der Entwicklungsumgebung etwas anders sein, sodass Sie möglicherweise die IWebHostEnvironment-Abhängigkeit entfernen möchten.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using YourMvcCoreProject.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Hosting;

namespace YourMvcCoreProject.Identity
{
    public class ClaimsManager
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly IWebHostEnvironment _env;
        private readonly ClaimsPrincipalAccessor _currentPrincipalAccessor;

        public ClaimsManager(
            ClaimsPrincipalAccessor currentPrincipalAccessor,
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            IWebHostEnvironment env)
        {
            _currentPrincipalAccessor = currentPrincipalAccessor;
            _userManager = userManager;
            _signInManager = signInManager;
            _env = env;
        }

        /// <param name="refreshSignin">Sometimes (e.g. when adding multiple claims at once) it is desirable to refresh cookie only once, for the last one </param>
        public async Task AddUpdateClaim(string claimType, string claimValue, bool refreshSignin = true)
        {
            await AddClaim(
                _currentPrincipalAccessor.ClaimsPrincipal,
                claimType,
                claimValue, 
                async user =>
                {
                    await RemoveClaim(_currentPrincipalAccessor.ClaimsPrincipal, user, claimType);
                },
                refreshSignin);
        }

        public async Task AddClaim(string claimType, string claimValue, bool refreshSignin = true)
        {
            await AddClaim(_currentPrincipalAccessor.ClaimsPrincipal, claimType, claimValue, refreshSignin);
        }

        /// <summary>
        /// At certain stages of user auth there is no user yet in context but there is one to work with in client code (e.g. calling from ClaimsTransformer)
        /// that's why we have principal as param
        /// </summary>
        public async Task AddClaim(ClaimsPrincipal principal, string claimType, string claimValue, bool refreshSignin = true)
        {
            await AddClaim(
                principal,
                claimType,
                claimValue, 
                async user =>
                {
                    // allow reassignment in dev
                    if (_env.IsDevelopment()) 
                        await RemoveClaim(principal, user, claimType);

                    if (GetClaim(principal, claimType) != null)
                        throw new ClaimCantBeReassignedException(claimType);                
                },
                refreshSignin);
        }

        public async Task RemoveClaims(IEnumerable<string> claimTypes, bool refreshSignin = true)
        {
            await RemoveClaims(_currentPrincipalAccessor.ClaimsPrincipal, claimTypes, refreshSignin);
        }

        public async Task RemoveClaims(ClaimsPrincipal principal, IEnumerable<string> claimTypes, bool refreshSignin = true)
        {
            AssertAuthenticated(principal);
            foreach (var claimType in claimTypes)
            {
                await RemoveClaim(principal, claimType);
            }
            // reflect the change in the Identity cookie
            if (refreshSignin)
                await _signInManager.RefreshSignInAsync(await _userManager.GetUserAsync(principal));
        }

        public async Task RemoveClaim(string claimType, bool refreshSignin = true)
        {
            await RemoveClaim(_currentPrincipalAccessor.ClaimsPrincipal, claimType, refreshSignin);
        }

        public async Task RemoveClaim(ClaimsPrincipal principal, string claimType, bool refreshSignin = true)
        {
            AssertAuthenticated(principal);
            var user = await _userManager.GetUserAsync(principal);
            await RemoveClaim(principal, user, claimType);
            // reflect the change in the Identity cookie
            if (refreshSignin)
                await _signInManager.RefreshSignInAsync(user);
        }

        private async Task AddClaim(ClaimsPrincipal principal, string claimType, string claimValue, Func<ApplicationUser, Task> processExistingClaims, bool refreshSignin)
        {
            AssertAuthenticated(principal);
            var user = await _userManager.GetUserAsync(principal);
            await processExistingClaims(user);
            var claim = new Claim(claimType, claimValue);
            ClaimsIdentity(principal).AddClaim(claim);
            await _userManager.AddClaimAsync(user, claim);
            // reflect the change in the Identity cookie
            if (refreshSignin)
                await _signInManager.RefreshSignInAsync(user);
        }

        /// <summary>
        /// Due to bugs or as result of debug it can be more than one identity of the same type.
        /// The method removes all the claims of a given type.
        /// </summary>
        private async Task RemoveClaim(ClaimsPrincipal principal, ApplicationUser user, string claimType)
        {
            AssertAuthenticated(principal);
            var identity = ClaimsIdentity(principal);
            var claims = identity.FindAll(claimType).ToArray();
            if (claims.Length > 0)
            {
                await _userManager.RemoveClaimsAsync(user, claims);
                foreach (var c in claims)
                {
                    identity.RemoveClaim(c);
                }
            }
        }

        private static Claim GetClaim(ClaimsPrincipal principal, string claimType)
        {
            return ClaimsIdentity(principal).FindFirst(claimType);    
        }    

        /// <summary>
        /// This kind of bugs has to be found during testing phase
        /// </summary>
        private static void AssertAuthenticated(ClaimsPrincipal principal)
        {
            if (!principal.Identity.IsAuthenticated)
                throw new InvalidOperationException("User should be authenticated in order to update claims");
        }

        private static ClaimsIdentity ClaimsIdentity(ClaimsPrincipal principal)
        {
            return (ClaimsIdentity) principal.Identity;
        }
    }


    public class ClaimCantBeReassignedException : Exception
    {
        public ClaimCantBeReassignedException(string claimType) : base($"{claimType} can not be reassigned")
        {
        }
    }

public class ClaimsPrincipalAccessor
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public ClaimsPrincipalAccessor(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public ClaimsPrincipal ClaimsPrincipal => _httpContextAccessor.HttpContext.User;
}

// to register dependency put this into your Startup.cs and inject ClaimsManager into Controller constructor (or other class) the in same way as you do for other dependencies    
public class Startup
{
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<ClaimsPrincipalAccessor>();
        services.AddTransient<ClaimsManager>();
    }
}

}}

Sasha
quelle
2

wenn ich MVC5 benutze und den Anspruch hier hinzufüge.

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(PATAUserManager 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
        userIdentity.AddClaim(new Claim(ClaimTypes.Role, this.Role));

        return userIdentity;
    }

Wenn ich das Anspruchsergebnis in der SignInAsync-Funktion überprüfe, kann ich den Rollenwert ohnehin nicht verwenden. Aber...

Nachdem diese Anforderung abgeschlossen wurde, kann ich in einer anderen Aktion (weitere Anforderung) auf Rolle zugreifen.

 var userWithClaims = (ClaimsPrincipal)User;
        Claim CRole = userWithClaims.Claims.First(c => c.Type == ClaimTypes.Role);

Ich denke also, dass die IEnumerable möglicherweise asynchron hinter dem Prozess aktualisiert wird.

user7372976
quelle
1

Sie können Ansprüche für den aktuellen Benutzer aktualisieren, indem Sie eine CookieAuthenticationEventsKlasse implementieren und überschreiben ValidatePrincipal. Dort können Sie den alten Anspruch entfernen, den neuen hinzufügen und dann den Principal mit ersetzen CookieValidatePrincipalContext.ReplacePrincipal. Dies hat keine Auswirkungen auf in der Datenbank gespeicherte Ansprüche. Dies verwendet ASP.NET Core Identity 2.2.

public class MyCookieAuthenticationEvents : CookieAuthenticationEvents
{
    string newAccountNo = "102";

    public override Task ValidatePrincipal(CookieValidatePrincipalContext context)
    {
        // first remove the old claim
        var claim = context.Principal.FindFirst(ClaimTypes.UserData);
        if (claim != null)
        {
            ((ClaimsIdentity)context.Principal.Identity).RemoveClaim(claim);
        }

        // add the new claim
        ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(ClaimTypes.UserData, newAccountNo));

        // replace the claims
        context.ReplacePrincipal(context.Principal);
        context.ShouldRenew = true;

        return Task.CompletedTask;
    }
}

Sie müssen die Ereignisklasse registrieren in Startup.cs:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddScoped<MyCookieAuthenticationEvents>();

    services.ConfigureApplicationCookie(o =>
    {
        o.EventsType = typeof(MyCookieAuthenticationEvents);
    });
}

Sie können Dienste in die Ereignisklasse einfügen, um auf den neuen AccountNoWert zuzugreifen. Gemäß der Warnung auf dieser Seite sollten Sie jedoch vermeiden, etwas zu teures zu tun:

Warnung

Der hier beschriebene Ansatz wird bei jeder Anfrage ausgelöst. Das Überprüfen von Authentifizierungscookies für alle Benutzer bei jeder Anforderung kann zu einer erheblichen Leistungsminderung für die App führen.

Simon C.
quelle
danke, das hat bei asp.net core 3.1 super geklappt!
darkezm0
0

Um Anspruchsdetails aus der Datenbank zu entfernen, können wir den folgenden Code verwenden. Außerdem müssen wir uns erneut anmelden, um die Cookie-Werte zu aktualisieren

 // create a new identity 
            var identity = new ClaimsIdentity(User.Identity);

            // Remove the existing claim value of current user from database
            if(identity.FindFirst("NameOfUser")!=null)
                await UserManager.RemoveClaimAsync(applicationUser.Id, identity.FindFirst("NameOfUser"));

            // Update customized claim 
            await UserManager.AddClaimAsync(applicationUser.Id, new Claim("NameOfUser", applicationUser.Name));

            // the claim has been updates, We need to change the cookie value for getting the updated claim
            AuthenticationManager.SignOut(identity.AuthenticationType);
            await SignInManager.SignInAsync(Userprofile, isPersistent: false, rememberBrowser: false);

            return RedirectToAction("Index", "Home");
Abdul Rahim
quelle
0

Mehrere Cookies, mehrere Ansprüche

public class ClaimsCookie
    {
        private readonly ClaimsPrincipal _user;
        private readonly HttpContext _httpContext;
        public ClaimsCookie(ClaimsPrincipal user, HttpContext httpContext = null)
        {
            _user = user;
            _httpContext = httpContext;
        }

        public string GetValue(CookieName cookieName, KeyName keyName)
        {
            var principal = _user as ClaimsPrincipal;
            var cp = principal.Identities.First(i => i.AuthenticationType == ((CookieName)cookieName).ToString());
            return cp.FindFirst(((KeyName)keyName).ToString()).Value;
        }
        public async void SetValue(CookieName cookieName, KeyName[] keyName, string[] value)
        {
            if (keyName.Length != value.Length)
            {
                return;
            }
            var principal = _user as ClaimsPrincipal;
            var cp = principal.Identities.First(i => i.AuthenticationType == ((CookieName)cookieName).ToString());
            for (int i = 0; i < keyName.Length; i++)
            {
                if (cp.FindFirst(((KeyName)keyName[i]).ToString()) != null)
                {
                    cp.RemoveClaim(cp.FindFirst(((KeyName)keyName[i]).ToString()));
                    cp.AddClaim(new Claim(((KeyName)keyName[i]).ToString(), value[i]));
                }

            }
            await _httpContext.SignOutAsync(CookieName.UserProfilCookie.ToString());
            await _httpContext.SignInAsync(CookieName.UserProfilCookie.ToString(), new ClaimsPrincipal(cp),
                new AuthenticationProperties
                {
                    IsPersistent = bool.Parse(cp.FindFirst(KeyName.IsPersistent.ToString()).Value),
                    AllowRefresh = true
                });
        }
        public enum CookieName
        {
            CompanyUserProfilCookie = 0, UserProfilCookie = 1, AdminPanelCookie = 2
        }
        public enum KeyName
        {
            Id, Name, Surname, Image, IsPersistent
        }
    }
OMANSAK
quelle
0
    if (HttpContext.User.Identity is ClaimsIdentity identity)
        {
            identity.RemoveClaim(identity.FindFirst("userId"));
            identity.AddClaim(new Claim("userId", userInfo?.id.ToString()));
            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(HttpContext.User.Identity));
        }
İbrahim Ayağıbüyük
quelle
6
Normalerweise ist es besser, eine Lösung zu erklären, als nur einige Zeilen anonymen Codes zu veröffentlichen. Sie können lesen, wie ich eine gute Antwort schreibe und auch vollständig codebasierte Antworten
erkläre
-1

Die Erweiterungsmethode hat bei mir hervorragend funktioniert, mit der Ausnahme, dass, wenn sich der Benutzer dort abmeldet, noch alte Anspruchssätze vorhanden sind. Mit einer winzigen Änderung wie beim Weiterleiten von usermanager funktioniert alles hervorragend und Sie müssen sich nicht abmelden und anmelden. Ich kann nicht direkt antworten, da mein Ruf beeinträchtigt wurde :(

public static class ClaimExtensions
{
    public static void AddUpdateClaim(this IPrincipal currentPrincipal,    string key, string value, ApplicationUserManager userManager)
    {
        var identity = currentPrincipal.Identity as ClaimsIdentity;
        if (identity == null)
            return;

        // check for existing claim and remove it
        var existingClaim = identity.FindFirst(key);
        if (existingClaim != null)
        {
            RemoveClaim(currentPrincipal, key, userManager);
        }

        // add new claim
        var claim = new Claim(key, value);
        identity.AddClaim(claim);
        var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
        authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
        //Persist to store
        userManager.AddClaim(identity.GetUserId(),claim);

    }

    public static void RemoveClaim(this IPrincipal currentPrincipal, string key, ApplicationUserManager userManager)
    {
        var identity = currentPrincipal.Identity as ClaimsIdentity;
        if (identity == null)
            return ;

        // check for existing claim and remove it
        var existingClaims = identity.FindAll(key);
        existingClaims.ForEach(c=> identity.RemoveClaim(c));

        //remove old claims from store
        var user = userManager.FindById(identity.GetUserId());
        var claims =  userManager.GetClaims(user.Id);
        claims.Where(x => x.Type == key).ToList().ForEach(c => userManager.RemoveClaim(user.Id, c));

    }

    public static string GetClaimValue(this IPrincipal currentPrincipal, string key)
    {
        var identity = currentPrincipal.Identity as ClaimsIdentity;
        if (identity == null)
            return null;

        var claim = identity.Claims.First(c => c.Type == key);
        return claim.Value;
    }

    public static string GetAllClaims(this IPrincipal currentPrincipal, ApplicationUserManager userManager)
    {
        var identity = currentPrincipal.Identity as ClaimsIdentity;
        if (identity == null)
            return null;

        var claims = userManager.GetClaims(identity.GetUserId());
        var userClaims = new StringBuilder();
        claims.ForEach(c => userClaims.AppendLine($"<li>{c.Type}, {c.Value}</li>"));
        return userClaims.ToString();
    }


}
user1158280
quelle
-2

Bitte schön:

            var user = User as ClaimsPrincipal;
            var identity = user.Identity as ClaimsIdentity;
            var claim = (from c in user.Claims
                         where c.Type == ClaimTypes.UserData
                         select c).Single();
            identity.RemoveClaim(claim);

von hier genommen.

RayLoveless
quelle