在我已经通过身份验证后,如何在 .NET Core 3.1 中 add/update 声明?

How can I add/update a claim in .NET Core 3.1 after I've already authenticated?

在我的场景中,用户和企业之间存在多对多关系。所以,一个企业可以有很多员工,一个用户可以是很多企业的员工。

在登录页面上,我只想显示电子邮件和密码文本框。一旦他们成功通过身份验证,我想将他们重定向到一个页面,该页面包含他们所雇用的企业的下拉列表。

由于他们已经通过身份验证,因此他们的声明已被填充。之后如何添加另一个声明(他们的 BusinessID)?

来自的答案是指何时进行身份验证并从 OAUTH 服务器获取声明。我们不知道您是否使用本地身份表或 OAUTH,但无论如何。

  1. 定义您自己的 UserClaimsPrincipalFactory class 实现
  2. 在启动 ConfigureServices 中注册为服务
  3. 当用户 select 业务类型时调用 GenerateClaimsAsync 方法。

我包含了一些旧代码(最后我们以另一种方式实现),但也许可以帮助你。

  1. 定义您自己的 UserClaimsPrincipalFactory。为此,我自定义了用户class,并添加了一个新工厂
    using System;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Security.Claims;
    using System.Text.Json.Serialization;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.Extensions.Options;
    
    namespace Common.Models.Identity {
        public class User : IdentityUser<int> {
    
    
            public bool SendAlertByEmail { get; set; }
            public int ClientId { get; set; } = Client.DefaultClientId;
            [JsonIgnore, ForeignKey("ClientId")]
            public virtual Client Client { get; set; } = null!;
        }
    
        public class ApplicationUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<User> {
            public ApplicationUserClaimsPrincipalFactory(
                            UserManager<User> userManager,
                            IOptions<IdentityOptions> optionsAccessor)
                            : base(userManager, optionsAccessor) {
            }
    
            protected override async Task<ClaimsIdentity> GenerateClaimsAsync(User user) {
                ClaimsIdentity identity;
    
                identity = await base.GenerateClaimsAsync(user);
                identity.AddClaim(new Claim("ClientId", user.ClientId.ToString()));
                identity.AddClaim(new Claim("ClientDescription", user.Client.Description));
                return identity;
            }
        }
    }
  1. 在您的 ConfigureServices 中,配置这个

     #region Configure identity
     services
         .AddDefaultIdentity<User>(
             options => {
                 options.SignIn.RequireConfirmedAccount = true;
                 options.Stores.MaxLengthForKeys = 256;            // Max length for key. Regenerate migration if change this
             })
         .AddEntityFrameworkStores<ApplicationDbContext>()
         .AddDefaultUI()
         .AddDefaultTokenProviders()
         .AddClaimsPrincipalFactory<ApplicationUserClaimsPrincipalFactory>();
    
     services.Configure<IdentityOptions>(options => {
         // Password settings.
         options.Password.RequireDigit = true;
         options.Password.RequireLowercase = true;
         options.Password.RequireNonAlphanumeric = true;
         options.Password.RequireUppercase = true;
         options.Password.RequiredLength = 6;
         options.Password.RequiredUniqueChars = 1;
    
         // Lockout settings.
         options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
         options.Lockout.MaxFailedAccessAttempts = 5;
         options.Lockout.AllowedForNewUsers = true;
    
         // User settings.
         options.User.AllowedUserNameCharacters =
         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
         options.User.RequireUniqueEmail = false;
     });
    
     services.ConfigureApplicationCookie(options => {
         // Cookie settings
         options.Cookie.HttpOnly = true;
         options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
    
         options.LoginPath = "/Identity/Account/Login";
         options.AccessDeniedPath = "/Identity/Account/AccessDenied";
         options.SlidingExpiration = true;
     });
     #endregion Configure identity
    
  2. 使用 IoC 将您的 ApplicationUserClaimsPrincipalFactory 传递给您的“Select business/client”请求,并使用它来添加声明