在 ASP.NET Identity 中删除唯一常量并使用户名可为空

问题描述 投票:0回答:4

我已经重写了一系列在 ASP.NET Identity 2.0 中使用的类,以便它们使用电子邮件地址字段而不是电子邮件字段。

当尝试创建用户时,它说

The UserName field is required.
我尝试覆盖我的
ApplicationUser
类中的UserName字段,该类继承自
IdentityUser
[Index(IsUnique = false)]
,但这只会导致唯一约束和非唯一索引已创建。

如何重写

IdentityUser
类以使用户名可为空且非唯一,因为我不想使用它。

注意: 我完全知道您可以使用

AllowOnlyAlphanumericUserNames
类中的
UserValidator
属性将电子邮件存储在用户名字段中。我真的不喜欢这种方法,只想删除这个限制,这样我就可以在没有用户名的情况下存储记录。我将修改我需要的使用用户名查看电子邮件地址的任何功能。

c# asp.net asp.net-mvc asp.net-identity
4个回答
1
投票

这是

IUserStore
的完整实现 - http://git.io/XZ3psA 我不会说有很多工作。


0
投票

摆脱它的唯一真正方法是实现你自己的

IUserStore
。这听起来像是大量的工作却几乎没有实际收益。

请参阅 UserManager 有方法

FindByNameAsync()
并且
IUserStore<TUser, in TKey>
还要求方法
Task<TUser> FindByNameAsync(string userName)
存在于实现类中。

此外,您还需要创建自己的

IdentityDbContext
实现,或者在
ApplicationDbContext
中创建所需的表/关系以删除唯一性验证。这也是另一项工作负担。

这根本不值得。


0
投票

我找到了最好的解决方案,只需在使用用户管理器之前清除用户验证器并编写自己的逻辑即可。无需重写任何类。

UserManager<ApplicationUser> userManager,

    userManager.UserValidators.Clear();

0
投票

我回答这个问题有点晚了,但我刚刚遇到这个问题,因为我需要允许用户仅使用他们的电话号码注册(没有用户名,没有电子邮件),同时还保持使用用户名的“正常”注册/电子邮件和密码。

这是我解决问题的方法(示例代码假设

User
是您的自定义
IdentityUser
类)。

  1. 创建您自己的
    IUserValidator<TUser>
    实现。您可以直接实现接口或子类
    UserValidator<TUser>
    :
public sealed class CustomUserValidator : UserValidator<User>
{
    public override async Task<IdentityResult> ValidateAsync(UserManager<User> manager, User user)
    {
        var result = await base.ValidateAsync(manager, user);
        if (result.Succeeded)
        {
            return result;
        }

        var errors = result.Errors.ToList();
        if (user.UserName is null)
        {
            var expectedError = Describer.InvalidUserName(user.UserName);
            errors.RemoveAll(x => x.Code == expectedError.Code);
        }

        if (user.Email is null)
        {
            var expectedError = Describer.InvalidEmail(user.Email);
            errors.RemoveAll(x => x.Code == expectedError.Code);
        }

        return errors.Count > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success;
    }
}
  1. 您可能还需要替换
    IUserClaimsPrincipalFactory<TUser>
    ,因为默认实现在尝试将其添加为声明之前不会检查用户名是否为
    null
    ,这会导致异常:
public sealed class CustomClaimsPrincipalFactory : IUserClaimsPrincipalFactory<User>
{
    public IdentityOptions Options { get; }

    public UserManager<User> UserManager { get; }

    public CustomClaimsPrincipalFactory(IOptions<IdentityOptions> options, UserManager<User> userManager)
    {
        Options = options.Value;
        UserManager = userManager;
    }

    public async Task<ClaimsPrincipal> CreateAsync(User user)
    {
        var claims = await GenerateClaimsAsync(user);
        return new ClaimsPrincipal(claims);
    }

    private async Task<ClaimsIdentity> GenerateClaimsAsync(User user)
    {
        var userId = user.Id.ToString();
        var claims = new ClaimsIdentity(
            IdentityConstants.ApplicationScheme,
            Options.ClaimsIdentity.UserNameClaimType,
            Options.ClaimsIdentity.RoleClaimType);

        claims.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));
        if (user.UserName is not null)
        {
            claims.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, user.UserName));
        }

        if (UserManager.SupportsUserSecurityStamp)
        {
            claims.AddClaim(new Claim(
                Options.ClaimsIdentity.SecurityStampClaimType,
                await UserManager.GetSecurityStampAsync(user)));
        }

        if (UserManager.SupportsUserClaim)
        {
            claims.AddClaims(await UserManager.GetClaimsAsync(user));
        }

        // Add more as needed

        return claims;
    }
}
  1. 在调用 AddIdentity 扩展方法之前
    注册您的服务:
services.AddScoped<IUserValidator<User>, CustomUserValidator>(); services.AddScoped<IUserClaimsPrincipalFactory<User>, CustomClaimsPrincipalFactory>();
之后,您可以使用空用户名调用

UserManager.CreateAsync

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.