UserManager.FindByEmailAsync returns null,但用户存在于数据库中
UserManager.FindByEmailAsync returns null, but the user exists in the database
UserManager.FindByEmailAsync
returnsnull
,但用户存在于数据库中。
下面的代码解释了这个奇怪的问题:
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
var test = new Data.ApplicationDbContext().Users.First(x => x.NormalizedEmail == email);
var usermail = await _userManager.FindByEmailAsync(email);
Console.WriteLine(test == null); //false
Console.WriteLine(usermail == null); //true
编辑
同样通过_userManager
本身,获得了想要的用户:
var test = _userManager.Users.FirstOrDefault(x => x.NormalizedEmail == email);
var usermail = await _userManager.FindByEmailAsync(email);
Console.WriteLine(test == null); //false
Console.WriteLine(usermail == null); //true
需要注意的是,用户不是以“常规”方式创建的,而是由 Data-Seed(在 OnModelCreating
中)创建的:
protected override void OnModelCreating(ModelBuilder builder)
{
var users = new (string email, string name)[] {
("xyz@gmail.com", "admin")
};
var appUsers = users.Select(x => new ApplicationUser
{
Email = x.email,
NormalizedEmail = x.email,
NormalizedUserName = x.email,
UserName = x.email,
EmailConfirmed = true,
Id = Guid.NewGuid().ToString(),
SecurityStamp = Guid.NewGuid().ToString()
}).ToArray();
var role = new IdentityRole("Admins") { Id = Guid.NewGuid().ToString() };
var roleToUser = appUsers.Select(x => new IdentityUserRole<string> { RoleId = role.Id, UserId = x.Id });
builder.Entity<ApplicationUser>().HasData(appUsers);
builder.Entity<IdentityRole>().HasData(role);
builder.Entity<IdentityUserRole<string>>().HasData(roleToUser);
base.OnModelCreating(builder);
}
对于NormalizedEmail
和NormalizedUserName
,应该是大写字母。
尝试
var appUsers = users.Select(x => new ApplicationUser
{
Email = x.email,
NormalizedEmail = x.email.ToUpper(),
NormalizedUserName = x.email.ToUpper(),
UserName = x.email,
EmailConfirmed = true,
Id = Guid.NewGuid().ToString(),
SecurityStamp = Guid.NewGuid().ToString()
}).ToArray();
正如您在我对您的 OP 的评论中的源代码链接中看到的
FindByEmailAsync performs a NormalizeKey 在实际开始搜索用户之前。
email = NormalizeKey(email);
此 NormalizeKey(email)
由 UpperInvariantLookupNormalizer 完成,它将对您的电子邮件执行以下字符串操作
return key.Normalize().ToUpperInvariant();
现在导致 "strange" 行为的代码部分是在创建用户时缺少对规范化的调用:
var appUsers = users.Select(x => new ApplicationUser
{
Email = x.email,
NormalizedEmail = x.email,
NormalizedUserName = x.email,
UserName = x.email,
EmailConfirmed = true,
Id = Guid.NewGuid().ToString(),
SecurityStamp = Guid.NewGuid().ToString()
}).ToArray();
不规范化电子邮件仍然可以通过用户 table 发现它,因为这只是将 NormalizedEmail
(您在创建用户时未规范化)与未规范化的电子邮件进行比较你作为参数传递:
_userManager.Users.FirstOrDefault(x => x.NormalizedEmail == email);
...但是,userManager.FindByEmailAsync
将 normalize it first and afterwards 进行搜索...
_userManager.FindByEmailAsync(email);
...因此找不到用户。
将您的代码更改为以下内容:
// inject via using Microsoft.AspNetCore.Identity
protected ILookupNormalizer normalizer;
var appUsers = users.Select(x => new ApplicationUser
{
Email = x.email,
NormalizedEmail = normalizer.Normalize(x.email),
NormalizedUserName = normalizer.Normalize(x.email),
UserName = x.email,
EmailConfirmed = true,
Id = Guid.NewGuid().ToString(),
SecurityStamp = Guid.NewGuid().ToString()
}).ToArray();
UserManager.FindByEmailAsync
returnsnull
,但用户存在于数据库中。
下面的代码解释了这个奇怪的问题:
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
var test = new Data.ApplicationDbContext().Users.First(x => x.NormalizedEmail == email);
var usermail = await _userManager.FindByEmailAsync(email);
Console.WriteLine(test == null); //false
Console.WriteLine(usermail == null); //true
编辑
同样通过_userManager
本身,获得了想要的用户:
var test = _userManager.Users.FirstOrDefault(x => x.NormalizedEmail == email);
var usermail = await _userManager.FindByEmailAsync(email);
Console.WriteLine(test == null); //false
Console.WriteLine(usermail == null); //true
需要注意的是,用户不是以“常规”方式创建的,而是由 Data-Seed(在 OnModelCreating
中)创建的:
protected override void OnModelCreating(ModelBuilder builder)
{
var users = new (string email, string name)[] {
("xyz@gmail.com", "admin")
};
var appUsers = users.Select(x => new ApplicationUser
{
Email = x.email,
NormalizedEmail = x.email,
NormalizedUserName = x.email,
UserName = x.email,
EmailConfirmed = true,
Id = Guid.NewGuid().ToString(),
SecurityStamp = Guid.NewGuid().ToString()
}).ToArray();
var role = new IdentityRole("Admins") { Id = Guid.NewGuid().ToString() };
var roleToUser = appUsers.Select(x => new IdentityUserRole<string> { RoleId = role.Id, UserId = x.Id });
builder.Entity<ApplicationUser>().HasData(appUsers);
builder.Entity<IdentityRole>().HasData(role);
builder.Entity<IdentityUserRole<string>>().HasData(roleToUser);
base.OnModelCreating(builder);
}
对于NormalizedEmail
和NormalizedUserName
,应该是大写字母。
尝试
var appUsers = users.Select(x => new ApplicationUser
{
Email = x.email,
NormalizedEmail = x.email.ToUpper(),
NormalizedUserName = x.email.ToUpper(),
UserName = x.email,
EmailConfirmed = true,
Id = Guid.NewGuid().ToString(),
SecurityStamp = Guid.NewGuid().ToString()
}).ToArray();
正如您在我对您的 OP 的评论中的源代码链接中看到的 FindByEmailAsync performs a NormalizeKey 在实际开始搜索用户之前。
email = NormalizeKey(email);
此 NormalizeKey(email)
由 UpperInvariantLookupNormalizer 完成,它将对您的电子邮件执行以下字符串操作
return key.Normalize().ToUpperInvariant();
现在导致 "strange" 行为的代码部分是在创建用户时缺少对规范化的调用:
var appUsers = users.Select(x => new ApplicationUser
{
Email = x.email,
NormalizedEmail = x.email,
NormalizedUserName = x.email,
UserName = x.email,
EmailConfirmed = true,
Id = Guid.NewGuid().ToString(),
SecurityStamp = Guid.NewGuid().ToString()
}).ToArray();
不规范化电子邮件仍然可以通过用户 table 发现它,因为这只是将 NormalizedEmail
(您在创建用户时未规范化)与未规范化的电子邮件进行比较你作为参数传递:
_userManager.Users.FirstOrDefault(x => x.NormalizedEmail == email);
...但是,userManager.FindByEmailAsync
将 normalize it first and afterwards 进行搜索...
_userManager.FindByEmailAsync(email);
...因此找不到用户。
将您的代码更改为以下内容:
// inject via using Microsoft.AspNetCore.Identity
protected ILookupNormalizer normalizer;
var appUsers = users.Select(x => new ApplicationUser
{
Email = x.email,
NormalizedEmail = normalizer.Normalize(x.email),
NormalizedUserName = normalizer.Normalize(x.email),
UserName = x.email,
EmailConfirmed = true,
Id = Guid.NewGuid().ToString(),
SecurityStamp = Guid.NewGuid().ToString()
}).ToArray();