向现有HttpContext用户添加了声明



我正在开发一个带有端点的ASP.NET Core 3.1 Web API,以便将新声明添加到现有的用户标识中。索赔已成功添加到身份,但是,在随后的请求中,添加的索赔不在索赔集合中,因此不可用。我还尝试添加一个新标识,为其分配声明,类似地,在后续请求中,添加的标识不在标识集合中。有什么想法吗?

var claims = new List<Claim>()
{
new Claim("token","value")
}
var identity = httpContextAccessor.HttpContext.User.Identities.FirstOrDefault();
identity.AddClaims(claims);

要将新添加的声明持久化到现有的HttpContext用户,可以实现自定义的CustomClaimsPrincipalFactory。进行以下步骤:

public class AppUser : IdentityUser
{
public string CompanyName { get; set; }
public string DisplayName { get; set; }
}
public static class IdentityExtensions
{
public static string FullName(this IIdentity identity)   //@User.Identity.FullName()
{
var claim = ((ClaimsIdentity)identity).FindFirst("DisplayName");
// Test for null to avoid issues during local testing
return (claim != null) ? claim.Value : string.Empty;
}
public static string GetCompanyName(this IIdentity identity)
{
if (identity == null)
throw new ArgumentNullException(nameof(identity));
var claim = ((ClaimsIdentity)identity).FindFirst("CompanyName");
// Test for null to avoid issues during local testing
return (claim != null) ? claim.Value : string.Empty;
}
}
public class CustomClaimsPrincipalFactory : UserClaimsPrincipalFactory<AppUser, IdentityRole>
{
public CustomClaimsPrincipalFactory(UserManager<AppUser> userManager, RoleManager<IdentityRole> roleManager,
IOptions<IdentityOptions> optionsAccessor)
: base(userManager, roleManager, optionsAccessor)
{
}
public override async Task<ClaimsPrincipal> CreateAsync(AppUser user)
{
if (user == null)
throw new ArgumentNullException(nameof(user));
var principal = await base.CreateAsync(user);
// Add your claims here
((ClaimsIdentity)principal.Identity).AddClaim(new Claim("CompanyName", user.CompanyName));
((ClaimsIdentity)principal.Identity).AddClaim(new Claim("DisplayName", user.DisplayName));
return principal;
}
}

注册CustomClaimsPrincipalFactory

public void Configure(IServiceCollection services)
{
...
services.AddScoped<IUserClaimsPrincipalFactory<AppUser>, CustomClaimsPrincipalFactory>();
});
}

您需要使用更新的ClaimsIdentity调用_signInManager.Context.SignInAsync

这是一个工作演示:

1.新ClaimsIdentity:签约扩展

public class CustomClaimsCookieSignInHelper<TIdentityUser> where TIdentityUser : IdentityUser
{
private readonly SignInManager<TIdentityUser> _signInManager;
public CustomClaimsCookieSignInHelper(SignInManager<TIdentityUser> signInManager)
{
_signInManager = signInManager;
}
public async Task SignInUserAsync(ClaimsIdentity claimsIdentity)
{
await _signInManager.Context.SignInAsync(IdentityConstants.ApplicationScheme, new ClaimsPrincipal(claimsIdentity));
}
}

2.寄存器CustomClaimsCookieSignInHelper<TIdentityUser>:

services.AddTransient<CustomClaimsCookieSignInHelper<IdentityUser>>();

3.更新用户声明:

public class IndexModel : PageModel
{
private readonly CustomClaimsCookieSignInHelper<IdentityUser> _signInHelper;
public IndexModel(CustomClaimsCookieSignInHelper<IdentityUser> signInHelper)
{
_signInHelper = signInHelper;            
}       
public async Task<IActionResult> OnGetAsync()
{
var claims = new List<Claim>()
{
new Claim("token","value")
};
var identity = HttpContext.User.Identities.FirstOrDefault();
identity.AddClaims(claims);
await _signInHelper.SignInUserAsync(identity);
return Page();
}
}

顺便说一句,如果你使用jwt authentication,当服务器端获得带有令牌的API调用时,AddJwtBearer将解码令牌,验证令牌并使用户通过身份验证,你可以在OnTokenValidated或自定义中间件中添加新的声明。但这种说法不会在接下来的api调用中持续存在。因此,如果您想在另一个请求中获得更新的声明,则必须颁发新的令牌。

最新更新