Добавлено утверждение к существующему пользователю HttpContext

#asp.net #.net #asp.net-core #.net-core #asp.net-core-webapi

#asp.net #.net #asp.net-core #.net-core #asp.net-core-webapi

Вопрос:

Я разрабатываю ASP.NET Ядро 3.1 Веб-API с конечной точкой для добавления нового утверждения к существующему идентификатору пользователя. Утверждение успешно добавляется к идентификатору, однако при последующих запросах добавленное утверждение отсутствует в коллекции утверждений, поэтому недоступно. Я также попытался добавить новое удостоверение, присвоив ему утверждение, аналогично при последующих запросах добавленное удостоверение отсутствует в коллекции удостоверений. Есть идеи?

 var claims = new List<Claim>()
{
    new Claim("token","value")
}

var identity = httpContextAccessor.HttpContext.User.Identities.FirstOrDefault();
identity.AddClaims(claims);
 

Комментарии:

1. HttpContext уникален для отдельного запроса. Добавление утверждения к идентификатору запроса (a) ничего не сделает для последующего запроса (b).

Ответ №1:

Чтобы сохранить вновь добавленные утверждения для существующего пользователя 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>();
        });
    }
 

Ответ №2:

Вам нужно позвонить _signInManager.Context.SignInAsync с обновленным ClaimsIdentity .

Вот рабочая демонстрация:

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.Поэтому, если вы хотите получить обновленное утверждение в другом запросе, должен быть выдан новый токен.