Đã 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;
}
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);
}
public async Task AddClaim(ClaimsPrincipal principal, string claimType, string claimValue, bool refreshSignin = true)
{
await AddClaim(
principal,
claimType,
claimValue,
async user =>
{
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);
}
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);
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);
if (refreshSignin)
await _signInManager.RefreshSignInAsync(user);
}
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);
}
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;
}
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddTransient<ClaimsPrincipalAccessor>();
services.AddTransient<ClaimsManager>();
}
}
}
SignInManager.SignInAsync
để làm mới giá trị của Khiếu nại. Xem câu hỏi này