it-swarm.com.de

Wie aktualisiere ich einen Anspruch in ASP.NET Identity?

Ich verwende die OWIN-Authentifizierung für mein MVC5-Projekt ... Dies ist mein _SignInAsync

 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, habe ich AccountNo in die Anspruchsliste aufgenommen.

Wie kann ich diesen Antrag an einem bestimmten Punkt 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, die Behauptung zu entfernen, erhalte ich folgende Ausnahme: 

Der Anspruch ' http://schemas.Microsoft.com/ws/2008/06/identity/claims/userdata : 101 'konnte nicht entfernt werden. Es ist entweder nicht Teil davon Identität oder ein Anspruch, der dem Auftraggeber gehört, der .__ enthält. diese Identität. Beispielsweise hat der Auftraggeber den Anspruch, wenn Erstellen eines GenericPrincipal mit Rollen. Die Rollen werden angezeigt durch die im Konstruktor übergebene Identität, jedoch nicht eigentlich im Besitz der Identität. Eine ähnliche Logik existiert für eine RolePrincipal.

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

68
Irshu

Sie können eine neue ClaimsIdentity erstellen und dann die Ansprüche mit solchen aktualisieren.

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 }
        );
}
43
Irshu

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");           
        }
    }
}
91
Frank Fu

Ein anderer (asynchroner) Ansatz, bei dem Identity UserManager und SigninManager verwendet werden, um die Änderung im Identity-Cookie wiederzugeben (und optional Ansprüche aus der db table 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);
  }
}
13
RickL

Ich bekomme auch diese Ausnahme und klärte die Dinge so auf

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);
6
IDisposable

wenn ich MVC5 verwende, und hier den Anspruch hinzufügen.

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 Claim-Ergebnis in der SignInAsync-Funktion überprüfe, kann ich den Rollenwert trotzdem nicht verwenden. Aber...

nachdem diese Anforderung abgeschlossen ist, kann ich auf die Rolle in einer anderen Aktion zugreifen (andere Anforderung).

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

also, ich denke, vielleicht asynchron, weil der IEnumerable hinter dem Prozess aktualisiert wurde.

2
user7372976

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

  1. Registrieren Sie eine UserClaimsPrincipalFactory, so dass die Ansprüche jedes Mal erstellt werden, wenn SignInManager den Benutzer einloggt.

    services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimService>();
    
  2. Implementieren Sie einen benutzerdefinierten 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 durch folgende Zeilen erreicht:

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

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

Anstatt vorhandene Ansprüche zu bearbeiten und Race-Bedingungen für sichere Cookies usw. zu erstellen, melden Sie den Benutzer einfach still an und aktualisieren den Status. :)

1
Mahmut C

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
        }
    }
0
OMANSAK

Um die Antragsdetails aus der Datenbank zu entfernen, können Sie 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");
0
Abdul Rahim
    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));
        }