【问题标题】:Require unique phone number in Asp.Net Core Identity在 Asp.Net Core Identity 中需要唯一的电话号码
【发布时间】:2018-06-14 14:19:09
【问题描述】:

在 Asp.Net Core Identity 框架中,我可以通过设置 RequireUniqueEmail = true 轻松要求唯一的电子邮件地址。

有没有办法对用户的电话号码做同样的事情?请注意,我不想要求确认的电话号码才能登录。用户不需要输入电话号码,但如果输入,它必须是唯一的。

【问题讨论】:

  • RequireConfirmed* 可用于电子邮件和电话,但 RequireUnique* 仅可用于电子邮件。这是有原因的吗?
  • 一个原因可能是允许用户使用 SMS 进行 2FA
  • 使用 SMS 进行 2FA 正是我需要唯一电话号码的原因。我不想要求提供确认的电话号码,因为允许用户使用电子邮件进行 2FA。
  • 抱歉,我误读了您的第一条评论。我认为 RequireUnique 仅可用于电子邮件的原因是许多站点将电子邮件用作登录凭据的一部分。在创建 Identity 时,Twitter 等网站可能尚未将电话号码作为登录凭据选项的一部分。因此,需求不足可能导致电话上没有 RequireUnique。

标签: asp.net-core unique asp.net-core-identity


【解决方案1】:

你可以试试这个,基本上是先在 Db 级别强制执行,然后在 Manager 级别执行适当的检查。

在 DbContext 中,我声明了用户名和电子邮件属性的索引和唯一性。

taken from the link

    // ================== 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 身份代码的完整性,同时强制执行我们想要的属性的唯一性。

请注意,以上示例目前适用于电子邮件。只需执行相同操作,然后在 UserManager.cs 中处理 SetPhoneNumberAsync,而不是修改 SetEmailAsync。

【讨论】:

    【解决方案2】:

    最简单的方法可能是在控制器中搜索电话号码...

    bool IsPhoneAlreadyRegistered = _userManager.Users.Any(item => item.PhoneNumber == model.PhoneNumber);
    

    【讨论】:

    • 这是一个快速且易于实施的解决方案。但是如果数据库中有超过一百万的用户,它会影响性能吗?
    • 这不起作用是同一个电话号码点击几毫秒不同我面临着与 1000 个用户相同的问题并获得了两个条目
    【解决方案3】:

    如果您使用的是 .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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-12
      • 2017-12-10
      • 2012-03-31
      • 2015-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多