Asp.Net Core Identity 中需要唯一的 phone 号码
Require unique phone number in Asp.Net Core Identity
在 Asp.Net Core Identity 框架中,我可以通过设置 RequireUniqueEmail = true 轻松地要求一个唯一的电子邮件地址。
有没有办法对用户的 phone 号码做同样的事情?请注意,我不想要求确认的 phone 号码才能登录。用户不需要输入 phone 号码,但如果输入,则它必须是唯一的。
您可以试试这个,基本上首先在 Db 级别强制执行,然后在 Manager 级别实施适当的检查。
在 DbContext,我声明了用户名和电子邮件属性的索引和唯一性。
// ================== Customizing IdentityCore Tables ================== //
builder.Entity<User>().ToTable("Users").Property(p => p.Id).HasColumnName("Id").ValueGeneratedOnAdd();
builder.Entity<User>(entity =>
{
entity.HasIndex(u => u.UserName).IsUnique();
entity.HasIndex(u => u.NormalizedUserName).IsUnique();
entity.HasIndex(u => u.Email).IsUnique();
entity.HasIndex(u => u.NormalizedEmail).IsUnique();
entity.Property(u => u.Rating).HasDefaultValue(0).IsRequired();
entity.HasMany(u => u.UserRoles).WithOne(ur => ur.User)
.HasForeignKey(ur => ur.UserId).OnDelete(DeleteBehavior.Restrict);
entity.HasMany(u => u.UserClaims).WithOne(uc => uc.User)
.HasForeignKey(uc => uc.UserId).OnDelete(DeleteBehavior.Restrict);
});
对于经理级别代码:
/// <summary>
/// Sets the <paramref name="email"/> address for a <paramref name="user"/>.
/// </summary>
/// <param name="user">The user whose email should be set.</param>
/// <param name="email">The email to set.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/>
/// of the operation.
/// </returns>
public override async Task<IdentityResult> SetEmailAsync(User user, string email)
{
var dupeUser = await FindByEmailAsync(email);
if (dupeUser != null)
{
return IdentityResult.Failed(new IdentityError() {
Code = "DuplicateEmailException", // Wrong practice, lets set some beautiful code values in the future
Description = "An existing user with the new email already exists."
});
}
// Perform dupe checks
// Code that runs in SetEmailAsync
// Adapted from: aspnet/Identity/blob/dev/src/Core/UserManager.cs
//
// ThrowIfDisposed();
// var store = GetEmailStore();
// if (user == null)
// {
// throw new ArgumentNullException(nameof(user));
// }
// await store.SetEmailAsync(user, email, CancellationToken);
// await store.SetEmailConfirmedAsync(user, false, CancellationToken);
// await UpdateSecurityStampInternal(user);
//return await UpdateUserAsync(user);
return await base.SetEmailAsync(user, email);
}
这样,我们保留了 .NET Core 身份代码的完整性,同时加强了我们想要的 property/properties 的唯一性。
请注意,以上示例目前适用于电子邮件。只需执行相同操作,然后不修改 SetEmailAsync,而是在 UserManager.cs.
处处理 SetPhoneNumberAsync
最简单的方法可能是在控制器中搜索 phone 号码...
bool IsPhoneAlreadyRegistered = _userManager.Users.Any(item => item.PhoneNumber == model.PhoneNumber);
如果您正在使用 .NET 5+ 和 EF Core 5.0+ 看看这个:
using Microsoft.EntityFrameworkCore;
[Index(nameof(PhoneNumber), IsUnique = true)]
public class ApplicationUser : IdentityUser
{
//...
}
public class MyDbContext : IdentityDbContext<ApplicationUser>
{
//...
}
参考:Entity Framework Core / Create a model / Indexes and constraints
在 Asp.Net Core Identity 框架中,我可以通过设置 RequireUniqueEmail = true 轻松地要求一个唯一的电子邮件地址。
有没有办法对用户的 phone 号码做同样的事情?请注意,我不想要求确认的 phone 号码才能登录。用户不需要输入 phone 号码,但如果输入,则它必须是唯一的。
您可以试试这个,基本上首先在 Db 级别强制执行,然后在 Manager 级别实施适当的检查。
在 DbContext,我声明了用户名和电子邮件属性的索引和唯一性。
// ================== Customizing IdentityCore Tables ================== //
builder.Entity<User>().ToTable("Users").Property(p => p.Id).HasColumnName("Id").ValueGeneratedOnAdd();
builder.Entity<User>(entity =>
{
entity.HasIndex(u => u.UserName).IsUnique();
entity.HasIndex(u => u.NormalizedUserName).IsUnique();
entity.HasIndex(u => u.Email).IsUnique();
entity.HasIndex(u => u.NormalizedEmail).IsUnique();
entity.Property(u => u.Rating).HasDefaultValue(0).IsRequired();
entity.HasMany(u => u.UserRoles).WithOne(ur => ur.User)
.HasForeignKey(ur => ur.UserId).OnDelete(DeleteBehavior.Restrict);
entity.HasMany(u => u.UserClaims).WithOne(uc => uc.User)
.HasForeignKey(uc => uc.UserId).OnDelete(DeleteBehavior.Restrict);
});
对于经理级别代码:
/// <summary>
/// Sets the <paramref name="email"/> address for a <paramref name="user"/>.
/// </summary>
/// <param name="user">The user whose email should be set.</param>
/// <param name="email">The email to set.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/>
/// of the operation.
/// </returns>
public override async Task<IdentityResult> SetEmailAsync(User user, string email)
{
var dupeUser = await FindByEmailAsync(email);
if (dupeUser != null)
{
return IdentityResult.Failed(new IdentityError() {
Code = "DuplicateEmailException", // Wrong practice, lets set some beautiful code values in the future
Description = "An existing user with the new email already exists."
});
}
// Perform dupe checks
// Code that runs in SetEmailAsync
// Adapted from: aspnet/Identity/blob/dev/src/Core/UserManager.cs
//
// ThrowIfDisposed();
// var store = GetEmailStore();
// if (user == null)
// {
// throw new ArgumentNullException(nameof(user));
// }
// await store.SetEmailAsync(user, email, CancellationToken);
// await store.SetEmailConfirmedAsync(user, false, CancellationToken);
// await UpdateSecurityStampInternal(user);
//return await UpdateUserAsync(user);
return await base.SetEmailAsync(user, email);
}
这样,我们保留了 .NET Core 身份代码的完整性,同时加强了我们想要的 property/properties 的唯一性。
请注意,以上示例目前适用于电子邮件。只需执行相同操作,然后不修改 SetEmailAsync,而是在 UserManager.cs.
处处理 SetPhoneNumberAsync最简单的方法可能是在控制器中搜索 phone 号码...
bool IsPhoneAlreadyRegistered = _userManager.Users.Any(item => item.PhoneNumber == model.PhoneNumber);
如果您正在使用 .NET 5+ 和 EF Core 5.0+ 看看这个:
using Microsoft.EntityFrameworkCore;
[Index(nameof(PhoneNumber), IsUnique = true)]
public class ApplicationUser : IdentityUser
{
//...
}
public class MyDbContext : IdentityDbContext<ApplicationUser>
{
//...
}
参考:Entity Framework Core / Create a model / Indexes and constraints