asp.net-core - 退出后无法重新登录
问题描述
使用 Visual Studio 2019、asp.net core 2.2 和 razor pages,我使用 Visual Studio 的功能添加“新的脚手架项目”,然后选择“身份”,然后我选择了帐户登录、帐户注销、忘记密码、拒绝访问,注册,重置密码选项。我添加了一个新的布局页面来与这些脚手架页面一起使用,这样我就可以控制它的样式和布局。登录,注册和更改密码都可以工作。问题是,一旦用户注销,他们就无法再次登录,登录的唯一方法是重置密码。这很奇怪,因为在 razor 页面操作的后端,我没有修改任何脚手架代码。
我尝试输入浏览器路由 /Account/Logout 以确保它正确注销。我在 Login 操作上使用了调试器,我可以看到该帐户没有被锁定。我没有启用两个因素,所以这不应该是问题。即使我 100% 确定密码正确,登录管理器也无法登录。
public void ConfigureServices(IServiceCollection services)
{
_sendGridApiKey = Configuration["AuthMessageSenderOptions:SendGridKey"];
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<MyAppDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<MyAppUser, IdentityRole>(config =>
{
config.User.RequireUniqueEmail = true;
})
.AddDefaultUI(UIFramework.Bootstrap4)
.AddRoleManager<RoleManager<IdentityRole>>()
.AddEntityFrameworkStores<MyAppDbContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireUppercase = true;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredLength = 8;
options.User.RequireUniqueEmail = false;
options.SignIn.RequireConfirmedEmail = true;
});
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddMvc().AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/");
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
登录管理器没有给出错误消息,但我可以通过调试器看到登录管理器无法对用户进行身份验证。如果我重置密码,登录管理器将成功。然后,在我明确注销后,相同的密码不再有效,我必须再次重置才能再次成功进行身份验证。
解决方案
在 signInManager 行下断点,发现结果是NotAllowed
."Not Allowed" 是有道理的,但是没有返回错误消息——所以这不是了解发生了什么的最好方法。幸运的是,.NET Core 很容易深入到源代码中。
NotAllowed 仅在此处设置:
protected virtual async Task<SignInResult> PreSignInCheck(TUser user)
{
if (!await CanSignInAsync(user))
{
return SignInResult.NotAllowed;
}
if (await IsLockedOut(user))
{
return await LockedOut(user);
}
return null;
}
CanSignInAsync 方法
public virtual async Task<bool> CanSignInAsync(TUser user)
{
if (Options.SignIn.RequireConfirmedEmail && !(await UserManager.IsEmailConfirmedAsync(user)))
{
Logger.LogWarning(0, "User {userId} cannot sign in without a confirmed email.", await UserManager.GetUserIdAsync(user));
return false;
}
if (Options.SignIn.RequireConfirmedPhoneNumber && !(await UserManager.IsPhoneNumberConfirmedAsync(user)))
{
Logger.LogWarning(1, "User {userId} cannot sign in without a confirmed phone number.", await UserManager.GetUserIdAsync(user));
return false;
}
return true;
}
那么问题的原因在于您的 Startup.cs 配置
services.Configure<IdentityOptions>(options =>
{
...
options.SignIn.RequireConfirmedEmail = true;
...
}
可以参考以下方法解决
1.pop进入数据库并将您的用户设置为EmailConfirmed = true
2.EmailConfirmed
在Register方法中设置为true,如下所示:
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
user.EmailConfirmed = true;
var result = await _userManager.CreateAsync(user, Input.Password);
推荐阅读
- android - du -sh 不显示这样的目录但它存在
- postgresql - Spring Boot Data JPA 引起:错误访问字段
- r - 关于ape包提供的parafit函数的问题
- python - 未填充参数
- python - Pytesseract image_to_data 函数
- html - 如何使用用户名、电子邮件、电话号码登录
- apache-spark - 当所有列都不在源中时,有没有办法在 Spark/Databricks 合并查询上“设置 *”?
- nginx - NGINX:如何使用不同的http方法以不同的方式处理对一个位置的请求
- reactjs - 使用反应状态更改谷歌地图方向
- laravel - 在 Laravel 中,为什么 !$request->expectsJson() 确定用户是否经过身份验证?