自定义UserManager始终返回null [英] Custom UserManager always return null

查看:73
本文介绍了自定义UserManager始终返回null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建自己的UserManager,从原始文档开始,并且当我通过电子邮件进行搜索时,找不到用户.但是,如果我从上下文进行搜索,是否找到了用户(请参见Get方法).为了验证它是否实现得很好,我改写了FindByEmailAsync方法并确实调用了该方法,但是我不知道为什么用户找不到它.一些帮助?谢谢!

I am trying to create my own UserManager extending from the original, and when I do a search by email, the user is not found. But if I do a search from the context, if I find the user (see the Get method). To verify that it is really well implemented, I overwrote the FindByEmailAsync method and it is really being called, but I do not know why the user can not find it. Some help? Thank you!

public void ConfigureServices(IServiceCollection servicesCollection)
{
    servicesCollection.AddDbContext<MyIndentityContext>(currentOptions =>
        currentOptions.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    servicesCollection.AddIdentity<ApplicationUser, ApplicationRole>()
        .AddEntityFrameworkStores<MyIndentityContext>()
        .AddRoleStore<ApplicationRoleStore>()
        .AddUserStore<ApplicationUserStore>()
        .AddUserManager<ApplicationUserManager>()
        .AddRoleManager<ApplicationRoleManager>()
        .AddSignInManager<ApplicationSignInManager>()
        .AddDefaultTokenProviders();

        ...

        ...

        ...
}

public class MyIndentityContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
    private readonly IConfiguration _configuration;

    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyIndentityContext(DbContextOptions dbContextOptions, IHttpContextAccessor httpContextAccessor,
        IConfiguration configuration)
        : base(dbContextOptions)
    {
        _configuration = configuration;
        _httpContextAccessor = httpContextAccessor;
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.HasDefaultSchema("Sample.API");
    }

}

public class ApplicationRoleManager : RoleManager<ApplicationRole>
{
    public ApplicationRoleManager(IRoleStore<ApplicationRole> roleStore,
        IEnumerable<IRoleValidator<ApplicationRole>> roleValidators, ILookupNormalizer keyNormalizer,
        IdentityErrorDescriber errors, ILogger<ApplicationRoleManager> logger) : base(roleStore,
        roleValidators,
        keyNormalizer, errors, logger)
    {
    }
}

public class ApplicationSignInManager : SignInManager<ApplicationUser>
{
    public ApplicationSignInManager(UserManager<ApplicationUser> userManager, IHttpContextAccessor contextAccessor,
        IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor,
        ILogger<ApplicationSignInManager> logger, IAuthenticationSchemeProvider schemes) : base(userManager,
        contextAccessor, claimsFactory, optionsAccessor, logger, schemes)
    {
    }
}

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> userStore, IOptions<IdentityOptions> optionsAccessor,
        IPasswordHasher<ApplicationUser> passwordHasher,
        IEnumerable<IUserValidator<ApplicationUser>> userValidators,
        IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer,
        IdentityErrorDescriber errors, IServiceProvider services, ILogger<ApplicationUserManager> logger) :
        base(userStore, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors,
            services, logger)
    { }

    // Custom implementation to check if you are really calling the method
    public override Task<ApplicationUser> FindByEmailAsync(string email)
    {
        return Task.Run(() => new ApplicationUser
        {
            UserName = "A_NAME"
        });
    }
}

public class ApplicationRoleStore : RoleStore<ApplicationRole, MyIndentityContext>
{
    public ApplicationRoleStore(MyIndentityContext dbContext, IdentityErrorDescriber identityErrorDescriber)
        : base(dbContext, identityErrorDescriber)
    {}
}

public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, MyIndentityContext, string>
{
    public ApplicationUserStore(MyIndentityContext dbContext, IdentityErrorDescriber identityErrorDescriber)
        : base(dbContext, identityErrorDescriber)
    {}

}

public class ApplicationUser : IdentityUser {}

public class ApplicationRole : IdentityRole
{
    public ApplicationRole() { }

    public ApplicationRole(string roleName) : base(roleName) { }

    public ApplicationRole(string roleName, string roleDescription) : base(roleName)
    {
        Description = roleDescription;
    }

}

[Authorize]
[ApiController]
[Route("api/[controller]")]
[EnableCors(CORS.AllowSpecificOrigins)]

public class UserController : BaseController
{
    private readonly ApplicationUserManager _applicationUserManager;

    public UserController(ApplicationUserManager applicationUserManager)
    {
        _applicationUserManager = applicationUserManager;
    }

     // GET: api/User/5
    [HttpGet("{id}")]
    public async Task<UserDTO> Get(int id)
    {

            var currentUser = await _applicationUserManager.FindByEmailAsync("example@example.com"); ==> RETURN NULL!

            var otherUser = _indentityContext.Users.Where(x => x.Email == "example@example.com"); ==> RETURN CORRECT USER!

            return currentUser;

    }

}

推荐答案

注意:该答案引用了Github复制程序中显​​示的代码和值.

当调用UserManager.FindByEmailAsync时,传递给方法的值将被规范化-默认情况下,此规范化将值转换为大写.然后,该标准化值将用于搜索AspNetUsers表中的NormalizedEmail列.

When you call UserManager.FindByEmailAsync, the value you pass into the method is normalised - by default, this normalisation converts the value to uppercase. This normalised value is then used to search the NormalizedEmail column in the AspNetUsers table.

MyIndentityContext.OnModelCreating方法内部,您具有以下代码:

Inside of your MyIndentityContext.OnModelCreating method, you have the following code:

modelBuilder.Entity<ApplicationUser>().HasData(
    new ApplicationUser
    {
        Email = "a_mail@hotmail.com"
    });

在这里控制数据并仅设置Email时,未设置数据库中的NormalizedEmail值(它是null).这意味着,当您使用UserManager.FindByEmailAsync并在NormalizedEmail列中查找A_MAIL@HOTMAIL.COM时,没有匹配项.但是,当直接使用DbSet并查看Email列时,可以找到与a_mail@hotmail.com匹配的记录.

As you're taking control of the data here and setting only Email, the NormalizedEmail value in the database is not being set (it's null). This means that when you use UserManager.FindByEmailAsync and are looking for A_MAIL@HOTMAIL.COM in the NormalizedEmail column, there's no match. However, when you use the DbSet directly and look at the Email column, you can find a matching record for a_mail@hotmail.com.

要解决此问题,我建议您在应用程序内的seed方法内部使用UserManager.CreateAsync方法,而不要使用HasData为用户设置种子.这样可以确保在将记录保留在数据库中之前,应进行规范化和其他相关处理.

To resolve this, I recommend that instead of using HasData to seed your user(s), you use the UserManager.CreateAsync method inside of a seed method within your application. This will ensure that normalisation and other related processing occurrs as it should before the records are persisted in the database.

这篇关于自定义UserManager始终返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆