在我已经通过身份验证后,如何在 .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,但无论如何。
- 定义您自己的 UserClaimsPrincipalFactory class 实现
- 在启动 ConfigureServices 中注册为服务
- 当用户 select 业务类型时调用 GenerateClaimsAsync 方法。
我包含了一些旧代码(最后我们以另一种方式实现),但也许可以帮助你。
- 定义您自己的 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;
}
}
}
在您的 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
使用 IoC 将您的 ApplicationUserClaimsPrincipalFactory 传递给您的“Select business/client”请求,并使用它来添加声明
在我的场景中,用户和企业之间存在多对多关系。所以,一个企业可以有很多员工,一个用户可以是很多企业的员工。
在登录页面上,我只想显示电子邮件和密码文本框。一旦他们成功通过身份验证,我想将他们重定向到一个页面,该页面包含他们所雇用的企业的下拉列表。
由于他们已经通过身份验证,因此他们的声明已被填充。之后如何添加另一个声明(他们的 BusinessID)?
来自的答案是指何时进行身份验证并从 OAUTH 服务器获取声明。我们不知道您是否使用本地身份表或 OAUTH,但无论如何。
- 定义您自己的 UserClaimsPrincipalFactory class 实现
- 在启动 ConfigureServices 中注册为服务
- 当用户 select 业务类型时调用 GenerateClaimsAsync 方法。
我包含了一些旧代码(最后我们以另一种方式实现),但也许可以帮助你。
- 定义您自己的 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;
}
}
}
在您的 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
使用 IoC 将您的 ApplicationUserClaimsPrincipalFactory 传递给您的“Select business/client”请求,并使用它来添加声明