我正在尝试向我的身份用户添加一些附加字段。 我发现通过创建一个继承自 IdentityUser 的新类并将继承的类传递给适当的构建器,这是相当简单的。
没关系,用户表有附加字段。但是,我正在努力找出如何自定义路由“/register”的请求正文,因为那里只请求电子邮件和密码。通常,我会在控制器类中调整这些内容,但 IdentityController 是一个我无权访问的黑匣子。
PS:我没有使用 Blazor。我纯粹使用 ASP.Net 作为后端。 PS2:我正在使用 Identity Core 8 升级非 Identity ASP.Net Core 7 项目
目前我得到的所有信息均来自官方文档: https://learn.microsoft.com/en-us/aspnet/core/migration/identity?view=aspnetcore-8.0 但他们总是提到他们的自定义 UI,这不是我想要的。
这是我的自定义用户类别
public class AuthUser: IdentityUser
{
public static readonly string KEY_PREFIX = "user";
// Would like to have a custom id generator but haven't
// figured out how to do that either
// [Key]
// public string Id { get; set; } = string.Empty;
[PersonalData]
[Required]
public string FirstName { get; set; } = string.Empty;
[PersonalData]
[Required]
public string LastName { get; set; } = string.Empty;
}
数据库类:
public class ApiDbContext: IdentityDbContext<AuthUser>
{
public ApiDbContext(DbContextOptions<ApiDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
/* ... */
}
这是我的 Program.cs 的一些内容
/* ... */
builder.Services.AddAuthorization();
// Setup Database
builder.Services.AddDbContext<ApiDbContext>(options => options.UseNpgsql(conn));
// Setup Auth
builder.Services.AddIdentityApiEndpoints<AuthUser>()
.AddEntityFrameworkStores<ApiDbContext>();
builder.Services.AddAuthentication(IdentityConstants.BearerScheme);
/* ... */
app.MapIdentityApi<AuthUser>();
// Not sure if this part is needed
app.UseAuthorization();
app.UseAuthentication();
/* ... */
我正在努力找出如何自定义请求正文 路由“/register”,因为那里只有电子邮件和密码 要求。通常,我会在我的控制器类中调整这些东西 但 IdentityController 是一个我无权访问的黑匣子。
如果我没理解错的话,您正在尝试实现一个场景,您可以选择根据请求路径或特定页面来验证
AuthUser
类属性。
嗯,这可以通过多种方式实现。例如,您可以使用 HttpContextAccessor 覆盖 IActionFilter 并获取请求路由或操作名称,甚至请求路径,以检查您的请求来源。
然后您只需检查您的请求模型属性状态是否为空。
最后,根据您的模型验证状态,您可以构建新创建的
ValidationResult
并更新用户。
另一种方法,通过使用 ModelBinderProvider
来做到这一点但是,根据您的场景,我认为使用 httpcontext 访问器操作过滤器机制更合适。所以我提供这个例子。
让我们看看如何在实践中实现:
检查http请求上下文:
public class HttpContextAccessorActionFilter : IActionFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextAccessorActionFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Items["ActionName"] = context.ActionDescriptor.RouteValues["action"];
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Do nothing
}
}
注意: 在这里,我们使用 IHttpContextAccessor 检查每个 http 请求上下文的请求来源。
使用 IHttpContextAccessor 验证请求模型:
我们看下面的截图:
如您所见,我必须执行您所说的任何操作,即登录和注册。因此,在下面的模型验证器 acion 过滤器中,我们将检查两条路由以验证我们的
AuthUser request model
。
[AttributeUsage(AttributeTargets.Class)]
public class ConditionalValidationAttribute : ValidationAttribute
{
public string[] Actions { get; }
public ConditionalValidationAttribute(params string[] actions)
{
Actions = actions;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var model = value as AuthUser;
if (model != null)
{
var httpContextAccessor = validationContext.GetRequiredService<IHttpContextAccessor>();
var actionName = httpContextAccessor.HttpContext.Request.RouteValues["action"]?.ToString();
var reqeustPath = httpContextAccessor.HttpContext.Request.Path;
if (Actions.Contains(actionName))
{
// Validate based on the action
if (actionName == "Login" && (string.IsNullOrEmpty(model.Email) || string.IsNullOrEmpty(model.Password)))
{
return new ValidationResult("Email and Password are required for login.", new[] { nameof(AuthUser.Email), nameof(AuthUser.Password) });
}
else if (actionName == "Register" && (string.IsNullOrEmpty(model.Email) || string.IsNullOrEmpty(model.Password) || string.IsNullOrEmpty(model.FirstName) || string.IsNullOrEmpty(model.LastName)))
{
return new ValidationResult("All fields are required for registration.", new[] { nameof(AuthUser.Email), nameof(AuthUser.Password), nameof(AuthUser.FirstName), nameof(AuthUser.LastName) });
}
}
}
return ValidationResult.Success;
}
}
注意: 如您所见,我正在根据每个请求路由检查模型,并且它仅适用于
AuthUser
类
Auth用户模型:
您的模型应如下所示:
[ConditionalValidation("Login", "Register")]
public class AuthUser : IdentityUser
{
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
}
程序.cs:
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add<HttpContextAccessorActionFilter>();
});
控制器:
[HttpPost]
public IActionResult Register(AuthUser model)
{
return View("Register");
}
输出:
注意:如果您还需要使用ModelBinderProvider实现的方法,您可以参考这个答案或查看官方文档。