Làm cách nào để cập nhật xác nhận quyền sở hữu trong ASP.NET Identity?


95

Tôi đang sử dụng xác thực OWIN cho dự án MVC5 của mình. Đây là của tôiSignInAsync

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

Như bạn có thể thấy, tôi đã thêm AccountNovào danh sách Yêu cầu bồi thường.

Bây giờ, làm cách nào để cập nhật Yêu cầu này vào một thời điểm nào đó trong ứng dụng của tôi? Cho đến nay, tôi có cái này:

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

        }

khi tôi cố gắng xóa xác nhận quyền sở hữu, tôi nhận được ngoại lệ này:

Không thể xóa Khiếu nại ' http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata : 101'. Nó không phải là một phần của Danh tính này hoặc đó là một xác nhận quyền sở hữu thuộc quyền sở hữu của Hiệu trưởng có chứa Danh tính này. Ví dụ: Hiệu trưởng sẽ sở hữu xác nhận quyền sở hữu khi tạo một GenericPrincipal với các vai trò. Các vai trò sẽ được hiển thị thông qua Danh tính được chuyển trong hàm khởi tạo, nhưng không thực sự thuộc sở hữu của Danh tính. Logic tương tự tồn tại cho một RolePrincipal.

Ai đó có thể giúp tôi tìm ra cách cập nhật Khiếu nại không?


Nếu bạn đang lưu trữ Thông tin Người dùng trong Yêu cầu và bạn muốn cập nhật Khiếu nại, khi Thông tin Người dùng đã thay đổi, bạn có thể gọi: SignInManager.SignInAsyncđể làm mới giá trị của Khiếu nại. Xem câu hỏi này
Hooman Bahreini 14/02/19

Câu trả lời:


125

Tôi đã tạo một phương thức Tiện ích mở rộng để Thêm / Cập nhật / Đọc xác nhận quyền sở hữu dựa trên một điểm xác nhận quyền sở hữu nhất định

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

và sau đó sử dụng nó

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

Cuối cùng. Tôi đã có một giải pháp khác cho điều này và nó dường như đang hoạt động ... hầu hết đều hoạt động. Nhưng cuối cùng đã chuyển sang phương pháp này vì nó dường như luôn hoạt động. Cảm ơn bạn!
saml

3
Có ai có giải pháp tương tự cho Asp.Net One Core không?
Martín

Điều này dường như chỉ hoạt động cho ứng dụng hiện tại. Tôi muốn cập nhật cookie do máy chủ SSO cấp để các ứng dụng khác cũng có thể truy cập chúng. Bất kỳ ý tưởng làm thế nào? Cảm ơn
Bất cứ ai

@ Bất kỳ ai Vì cookie được máy chủ SSO ký để chứng tỏ rằng nó không bị giả mạo (và do đó có thể tin cậy được), tôi sẽ ngạc nhiên nếu có bất kỳ cách nào để đạt được điều này vì nó sẽ bị giả mạo.
Mog0

2
var tuyên bố = danh tính.Claims.First (c => c.Type == key); trả về bồi thường.Value; phải là var tuyên bố = danh tính.Claims.FirstOrDefault (c => c.Type == key); yêu cầu trả lại?. giá trị;
liuhongbo

57

Bạn có thể tạo mới ClaimsIdentityvà sau đó cập nhật xác nhận quyền sở hữu với như vậy.

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
Bạn có thể cập nhật xác nhận quyền sở hữu nhưng vẫn cần đăng xuất và đăng nhập người dùng với danh tính được cập nhật.
user3210546

3
không nó không đăng xuất người dùng, chúng tôi chỉ cập nhật cookie của người dùng
Irshu

5
Hãy nhớ rằng điều này chỉ cập nhật danh tính. Nếu bạn muốn lưu trữ các xác nhận quyền sở hữu này và tải chúng tự động theo yêu cầu, bạn cũng cần người quản lý chúng tôi xóa và cập nhật chúng. Cho tôi một chút thời gian! :(
Dennis van der Stelt

3
Điều gì sẽ xảy ra nếu tôi không có cookie và chỉ sử dụng accessToken? Trong trường hợp của tôi, yêu cầu tiếp theo giống như trước khi thay đổi. Cách duy nhất để cập nhật các xác nhận quyền sở hữu mà tôi có là đăng xuất người dùng và yêu cầu anh ta đăng nhập lại :-(
Nozim Turakulov

1
Điều này dường như chỉ hoạt động cho ứng dụng hiện tại. Tôi muốn cập nhật cookie do máy chủ SSO cấp để các ứng dụng khác cũng có thể truy cập chúng. Bất kỳ ý tưởng làm thế nào? Cảm ơn
Bất cứ ai

18

Một cách tiếp cận (không đồng bộ) khác, sử dụng UserManager và SigninManager của Identity để phản ánh sự thay đổi trong cookie Identity (và để tùy chọn xóa các xác nhận quyền sở hữu khỏi bảng 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);
  }
}

Đầu mối ở đây, đối với tôi, là thực hiện SignInAsync() sau khi thiết lập Yêu cầu.
H Dog

Cảm ơn vì mẹo xóa các xác nhận quyền sở hữu khỏi DB. Khiến tôi nhận ra rằng mình cần phải dọn dẹp lại bản thân.
Uber Schnoz

13

Sử dụng Asp.Net Identity mới nhất với .net core 2.1, tôi có thể cập nhật các xác nhận quyền sở hữu của người dùng với logic sau.

  1. Đăng ký một UserClaimsPrincipalFactoryđể mỗi khi SignInManagerngười dùng đăng nhập, các xác nhận quyền sở hữu được tạo ra.

    services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimService>();
    
  2. Triển khai một tùy chỉnh UserClaimsPrincipalFactory<TUser, TRole>như bên dưới

    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. Sau này trong ứng dụng của bạn khi bạn thay đổi điều gì đó trong DB và muốn phản ánh điều này cho người dùng đã xác thực và đăng nhập của bạn, các dòng sau đạt được điều này:

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

Điều này đảm bảo người dùng có thể xem thông tin cập nhật mà không cần đăng nhập lại. Tôi đặt điều này ngay trước khi trả về kết quả trong bộ điều khiển để khi hoạt động kết thúc, mọi thứ được làm mới một cách an toàn.

Thay vì chỉnh sửa các xác nhận quyền sở hữu hiện có và tạo điều kiện chạy đua cho cookie an toàn, v.v., bạn chỉ cần âm thầm đăng nhập người dùng và làm mới trạng thái :)


Cảm ơn, đã gặp phải vấn đề tương tự và giải pháp này hoạt động tốt hơn để cập nhật các xác nhận quyền sở hữu cho người dùng đã ký.
ameya

Cảm ơn! cũng gặp phải vấn đề tương tự trong net core 3.1
Kevin Tran ngày

7

Tôi cũng nhận được ngoại lệ đó và làm rõ mọi thứ như thế này

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

Đã tổng hợp một số câu trả lời từ đây vào lớp ClaimsManager có thể sử dụng lại với các phần bổ sung của tôi.

Các xác nhận quyền sở hữu vẫn tồn tại, cookie của người dùng được cập nhật, đăng nhập được làm mới.

Xin lưu ý rằng ApplicationUser có thể được thay thế bằng IdentityUser nếu trước đây bạn không tùy chỉnh. Cũng trong trường hợp của tôi, nó cần có logic hơi khác trong môi trường Phát triển, vì vậy bạn có thể muốn loại bỏ sự phụ thuộc của IWebHostEnosystem.

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

khi tôi sử dụng MVC5 và thêm yêu cầu tại đây.

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

khi tôi kiểm tra kết quả xác nhận quyền sở hữu trong chức năng SignInAsync, tôi vẫn không thể sử dụng giá trị vai trò. Nhưng...

sau khi yêu cầu này kết thúc, tôi có thể truy cập Vai trò trong hành động khác (yêu cầu bao phấn).

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

vì vậy, tôi nghĩ rằng có thể không đồng bộ khiến IEnumerable được cập nhật đằng sau quá trình.


1

Bạn có thể cập nhật các xác nhận quyền sở hữu cho người dùng hiện tại bằng cách triển khai một CookieAuthenticationEventslớp và ghi đè ValidatePrincipal. Ở đó, bạn có thể xóa yêu cầu cũ, thêm yêu cầu mới và sau đó thay thế yêu cầu chính bằng cách sử dụng CookieValidatePrincipalContext.ReplacePrincipal. Điều này không ảnh hưởng đến bất kỳ yêu cầu nào được lưu trữ trong cơ sở dữ liệu. Điều này đang sử dụng 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;
    }
}

Bạn cần đăng ký lớp sự kiện trong Startup.cs:

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

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

Bạn có thể đưa các dịch vụ vào lớp sự kiện để truy cập AccountNogiá trị mới nhưng theo cảnh báo trên trang này, bạn nên tránh làm bất cứ điều gì quá tốn kém:

Cảnh báo

Cách tiếp cận được mô tả ở đây được kích hoạt theo mọi yêu cầu. Việc xác thực cookie xác thực cho tất cả người dùng theo mọi yêu cầu có thể dẫn đến hình phạt hiệu suất lớn cho ứng dụng.


cảm ơn, điều này rất hiệu quả đối với tôi trong asp.net core 3.1!
darkzm0

0

Để xóa chi tiết yêu cầu khỏi cơ sở dữ liệu, chúng tôi có thể sử dụng mã bên dưới. Ngoài ra, chúng tôi cần đăng nhập lại để cập nhật các giá trị 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

Nhiều cookie, nhiều xác nhận quyền sở hữu

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
Thông thường, tốt hơn là giải thích một giải pháp thay vì chỉ đăng một số hàng mã ẩn danh. Bạn có thể đọc Làm thế nào để tôi viết một câu trả lời hay , và cả Giải thích các câu trả lời hoàn toàn dựa trên mã
Anh Pham

0

Tôi đang sử dụng ứng dụng .net core 2.2 và đã sử dụng giải pháp sau: trong statup.cs của tôi

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

sử dụng

  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

Phương thức tiện ích mở rộng hoạt động tuyệt vời đối với tôi, ngoại trừ một ngoại lệ là nếu người dùng đăng xuất khỏi đó, các bộ xác nhận quyền sở hữu cũ vẫn tồn tại, vì vậy với một sửa đổi nhỏ như khi chuyển usermanager qua mọi thứ đều hoạt động tốt và bạn không cần đăng xuất và đăng nhập. Tôi không thể trả lời trực tiếp vì danh tiếng của tôi đã bị phân tán :(

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

Của bạn đây:

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

lấy từ đây.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.