Як оновити претензію в ASP.NET Identity?


93

Я використовую автентифікацію OWIN для свого проекту MVC5. Це моє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);
        }

Як бачите, я додав AccountNoдо списку претензій.

Тепер, як я можу оновити цю Претензію в якийсь момент моєї заявки? Поки що я маю таке:

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

        }

Коли я намагаюся видалити претензію, я отримую такий виняток:

Претензію " http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata : 101" не вдалося видалити. Це або не є частиною цього посвідчення, або це позов, який належить довірителю, що містить цю посвідчення. Наприклад, Принципал володітиме претензією під час створення GenericPrincipal з ролями. Ролі будуть виставлені через ідентичність, яка передається в конструкторі, але фактично не належить ідентичності. Подібна логіка існує для RolePrincipal.

Хтось може допомогти мені зрозуміти, як оновити Претензію?


Якщо ви зберігаєте інформацію про користувача у претензії і хочете оновити претензію, як тільки інформація про користувача зміниться, ви можете зателефонувати: SignInManager.SignInAsyncдля оновлення значення претензії. Подивіться це питання
Хооман Бахреїні

Відповіді:


123

Я створив метод розширення для додавання / оновлення / читання претензій на основі заданої ClaimsIdentity

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;
            }
    }
}

а потім використовувати його

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

Нарешті. У мене було інше рішення, і воно, здавалося, працювало ... переважно. Але зрештою перейшов на цей метод, оскільки він, здається, працює завжди. Дякую!
saml

3
У когось є таке саме рішення для Asp.Net One Core?
Мартін,

Здається, це працює лише для поточної програми. Я хотів би оновити файл cookie, виданий сервером SSO, щоб інші програми також мали до них доступ. Будь-яка ідея як? Дякую
Хто

@Whoever Оскільки файл cookie підписується сервером єдиного входу, щоб показати, що він не підроблявся (і, отже, йому можна довіряти), я був би здивований, якби це можна було досягти, оскільки це було б фальсифікацією.
Mog0

2
var претензія = ідентичність.Претензії.Перша (c => c.Type == ключ); повернути претензію.Значення; має бути var претензія = ідентичність.Claims.FirstOrDefault (c => c.Type == ключ); повернути претензію? .Значення;
liuhongbo

57

Ви можете створити новий, ClaimsIdentityа потім оновити претензії з ним.

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

4
Ви можете оновити претензію, але все одно потрібно вийти з системи та ввійти з оновленою ідентифікацією.
user3210546

3
ні, це не виходить з користувача, ми просто оновлюємо файл cookie користувача
Irshu

5
Пам'ятайте, що це оновлює лише ідентичність. Якщо ви хочете зберегти ці претензії та завантажити їх автоматично за запитом, вам потрібно, щоб менеджер користувачів також видалив та оновив їх. Зайняв у мене трохи часу! :(
Денніс ван дер Стелт,

3
Що робити, якщо я взагалі не маю файлів cookie і використовую лише accessToken? У моєму випадку вимоги однакові при наступному запиті, як і до зміни. Єдиний спосіб оновити претензії, які я маю, - це вийти з користувача та попросити його ще раз увійти :-(
Нозім Туракулов,

1
Здається, це працює лише для поточної програми. Я хотів би оновити файл cookie, виданий сервером SSO, щоб інші програми також мали до них доступ. Будь-яка ідея як? Дякую
Хто

18

Інший (асинхронний) підхід, який використовує Identity's UserManager і SigninManager, щоб відобразити зміни в файлі cookie Identity (і необов’язково видалити твердження з таблиці db AspNetUserClaims):

// 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);
  }
}

Підказкою тут, для мене, було зробити SignInAsync() після встановлення Претензій.
H Dog

Дякуємо за підказку щодо видалення претензій з БД. Змусив мене зрозуміти, що мені потрібно прибрати за собою.
Uber Schnoz

13

Використовуючи останню Asp.Net Identity з .net core 2.1, я можу оновлювати заявки користувачів за такою логікою.

  1. Зареєструйтесь, UserClaimsPrincipalFactoryщоб кожен раз, коли SignInManagerспіває користувач, створювалися претензії.

    services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimService>();
    
  2. Впровадьте користувальницькі дії, UserClaimsPrincipalFactory<TUser, TRole>як показано нижче

    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. Пізніше у вашій програмі, коли ви щось зміните в БД і хочете відобразити це вашому авторизованому та авторизованому користувачеві, наступні рядки досягають цього:

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

Це гарантує, що користувач може бачити актуальну інформацію, не вимагаючи входу знову. Я помістив це безпосередньо перед тим, як повернути результат у контролер, щоб після завершення операції все надійно оновилося.

Замість того, щоб редагувати існуючі претензії та створювати умови змагань для безпечного файлу cookie тощо, ви просто мовчки підписуєте користувача та оновлюєте стан :)


Дякуємо, зіткнулися з тією ж проблемою, і це рішення працює краще для оновлення заявок для підписаного користувача.
Амея

Дякую! зіткнувся з такою ж проблемою і в мережевому ядрі 3.1
Кевін Тран

7

Я теж отримую цей виняток і розбираюсь так

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

4

Зібрав кілька відповідей звідси на багаторазовий ClaimsManager клас з моїми доповненнями.

Претензії збережено, кукі-файл користувача оновлено, вхід оновлено.

Зверніть увагу, що ApplicationUser можна замінити IdentityUser, якщо ви не налаштували попередній. Крім того, у моєму випадку він повинен мати дещо іншу логіку в середовищі розробки, тому ви можете видалити залежність IWebHostEnvironment.

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>();
    }
}

}


2

коли я використовую MVC5, і додаю претензію сюди.

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;
    }

коли я перевіряю результат претензії у функції SignInAsync, я все одно не можу отримати значення значення ролі. Але ...

після завершення цього запиту я можу отримати доступ до ролі в іншій дії (запит на пиляк).

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

так що, я думаю, можливо асинхронна причина IEnumerable оновлена ​​за процесом.


1

Ви можете оновити претензії для поточного користувача, реалізувавши CookieAuthenticationEventsклас і замінивши ValidatePrincipal. Там ви можете видалити стару претензію, додати нову, а потім замінити основну за допомогою CookieValidatePrincipalContext.ReplacePrincipal. Це не впливає на будь-які претензії, що зберігаються в базі даних. Для цього використовується 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;
    }
}

Вам потрібно зареєструвати клас подій у Startup.cs:

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

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

Ви можете вводити служби в клас подій, щоб отримати доступ до нового AccountNoзначення, але згідно з попередженням на цій сторінці, вам слід уникати робити щось занадто дороге:

Увага

Описаний тут підхід застосовується до кожного запиту. Перевірка файлів cookie для автентифікації для всіх користувачів за кожним запитом може призвести до великого штрафу за продуктивність програми.


спасибі, це чудово спрацювало для мене в asp.net core 3.1!
darkezm0

0

Щоб видалити деталі претензії з бази даних, ми можемо використовувати код нижче. Крім того, нам потрібно ввійти ще раз, щоб оновити значення файлів cookie

 // 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

Кілька файлів cookie, кілька претензій

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

7
Зазвичай краще пояснити рішення, а не просто публікувати кілька рядків анонімного коду. Ви можете прочитати Як написати хорошу відповідь , а також пояснити цілком кодові відповіді
Anh Pham,

0

Я використовую додаток .net core 2.2 і використовував таке рішення: у моєму statup.cs

public void ConfigureServices(IServiceCollection services)
        {
        ...
           services.AddIdentity<IdentityUser, IdentityRole>(options =>
               {
                  ...
               })
               .AddEntityFrameworkStores<AdminDbContext>()
               .AddDefaultTokenProviders()
               .AddSignInManager();

використання

  private readonly SignInManager<IdentityUser> _signInManager;


        public YourController(
                                    ...,
SignInManager<IdentityUser> signInManager)
        {
           ...
            _signInManager = signInManager;
        }

 public async Task<IActionResult> YourMethod() // <-NOTE IT IS ASYNC
        {
                var user = _userManager.FindByNameAsync(User.Identity.Name).Result;
                var claimToUse = ClaimsHelpers.CreateClaim(ClaimTypes.ActiveCompany, JsonConvert.SerializeObject(cc));
                var claimToRemove = _userManager.GetClaimsAsync(user).Result
                    .FirstOrDefault(x => x.Type == ClaimTypes.ActiveCompany.ToString());
                if (claimToRemove != null)
                {
                    var result = _userManager.ReplaceClaimAsync(user, claimToRemove, claimToUse).Result;
                    await _signInManager.RefreshSignInAsync(user); //<--- THIS
                }
                else ...
              

-1

Для мене метод розширення чудово працював, за винятком того, що якщо користувач виходить із системи, старі набори претензій все ще існують, то з незначною модифікацією, як при проходженні менеджера користувачів через все, що працює чудово, і вам не потрібно виходити з системи та входити в систему. Я не можу відповісти прямо, оскільки мою репутацію заперечили :(

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();
    }


}

-2

Ось:

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

взято звідси.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.