登录到我的新 Razor Pages 应用程序时出现“无效登录”

Posted

技术标签:

【中文标题】登录到我的新 Razor Pages 应用程序时出现“无效登录”【英文标题】:"Invalid login" when logging into my new Razor Pages app 【发布时间】:2021-09-24 12:05:25 【问题描述】:

我创建了一个新的 Razor Pages 应用程序。我运行了那个应用程序并创建了一个帐户。 (发送了一封确认电子邮件,我点击了它。)该帐户正在运行。但是今天,我无法登录。

登录尝试无效。

尽管我相信我记得密码,但我还是尝试了忘记密码功能。没有发送电子邮件。

我已在数据库中查看了我的帐户。以下是 AspNetUsers 表中相关列的值:

EmailConfirmed: True LockoutEnd: NULL AccessFailedCount: 0

接下来,我尝试搭建登录和忘记密码的脚手架,以便调试代码。但这失败了。 (你可以在GitHub看到我关于这个问题的帖子。)

所以在这一点上,我被阻止了。其他人可以建议我可能尝试解决此问题的其他事情吗?还有哪些其他因素会导致这种行为?

【问题讨论】:

你能用新的脚手架重现这个吗?这似乎只是原始脚手架的一个奇怪的一次性错误。 @Deckerz:嗯,这是一个新项目/脚手架。问题是,它工作正常,但随后停止工作。所以我的猜测是代码按设计工作,但存在问题,出于安全考虑,它不会告诉我问题。 【参考方案1】:

SignInManager.PasswordSignInAsync 需要用户名和密码,而不是电子邮件和密码,因此如果您的用户名与电子邮件相同,它将与您一起使用,否则将无法使用。所以请确保 UserName 值 = Email

另外,最好通过等待_userManager.FindByEmailAsync(Input.Email) 来查询用户然后将此用户传递给PasswordSignInAsync 确保FindByEmailAsync 以检查具有给定名称的用户是否存在如下内容:-

var user = await _userManager.FindByEmailAsync(Input.Email);
var result = await _signInManager.PasswordSignInAsync(user, Input.Password, Input.RememberMe, lockoutOnFailure: false);

我认为这将有助于解决您的问题。

【讨论】:

我认为您的答案在某些方面偏离了轨道。首先,Razor Pages 的默认身份设置是使用电子邮件作为用户名。登录提示甚至说 Email。所以我不知道为什么你会认为它不同。其次,我使用的是 Visual Studio 生成的身份代码。所以,如果它错了,那么微软就是错的。此外,正如我在问题中解释的那样,我无法更改代码,因为我无法搭建它。代码保留在 .NET 库内部。 @JonathanWood 我实际上没有注意到您使用的是默认身份。所以你有一个脚手架问题。这是我的答案***.com/questions/67512332/… 请检查我的答案并尝试解决您的脚手架问题。【参考方案2】:

现在您检查是否设置了用户名值 = 电子邮件。或者没有 因为在 asp.net 核心身份中默认使用用户名登录

【讨论】:

如本问题其他地方所述,默认使用电子邮件作为用户名。【参考方案3】:

我也遇到过类似的情况,在我的情况下,在 db 表中记录的用户的安全标记值已以某种方式被删除。

如果您使用电子邮件作为用户名,还要检查用户名列是否具有电子邮件列的 sama 值。

如果您默认使用脚手架身份,则用户名列会重复电子邮件值。

【讨论】:

您指的是什么安全标记(表格和列)? aspnet users表中有一个名为securitystamp的列 AspNetUsers.SecurityStamp 列不为空。【参考方案4】:

请尝试从具有不同互联网连接的另一台计算机登录 - 这也是我遇到的问题 - 我通过使用具有相同密码和用户名的另一台计算机解决了这个问题

【讨论】:

网站在我的电脑上本地运行。并且不同的互联网连接永远不会产生我所看到的结果。【参考方案5】:

“无效的登录尝试”通常表示用户名或密码不正确。最有可能的密码。

我发现我无法收到任何电子邮件,因此通过电子邮件重置密码不是默认脚手架项目中的选项。

这是一种重置密码的方法:注册一个新用户(记住密码:-)),进入数据库并从新用户那里复制密码哈希并将其应用于您有问题的用户,看看它是否立即使用新密码登录。

更新

“无效登录尝试”的真正原因并未向用户透露,但已记录在案。因此,如果您在调试模式下运行应用程序,它将捕获原因。例如。如果我输入了错误的密码,我将在输出控制台中得到以下信息:

警告:Microsoft.AspNetCore.Identity.UserManager[0]

  Invalid password for user.

警告:Microsoft.AspNetCore.Identity.SignInManager[2]

  User failed to provide the correct password.

更新:当您收到“无效登录尝试”时的登录流程(Razor 页面)

https://github.com/aspnet/Identity/blob/master/src/UI/Areas/Identity/Pages/V4/Account/Login.cshtml.cs

您收到“无效登录尝试”,因为 _signInManager.PasswordSignInAsync 方法返回 SignResult.Failed 或 SignInResult.NotAllowed

public override async Task<IActionResult> OnPostAsync(string returnUrl = null)
   ....
          ModelState.AddModelError(string.Empty, "Invalid login attempt.");

https://github.com/aspnet/Identity/blob/master/src/Identity/SignInManager.cs

如果找不到用户,您会得到 SignInResult.Failed 且不记录

public virtual async Task<SignInResult> PasswordSignInAsync(string userName, string password,
            bool isPersistent, bool lockoutOnFailure)
        
            var user = await UserManager.FindByNameAsync(userName);
            if (user == null)
            

                return SignInResult.Failed;
            

            return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
        

此方法调用下面的方法,该方法只返回错误、SignInResult.Success 或输出日志消息:

public virtual async Task<SignInResult> CheckPasswordSignInAsync(TUser user, string password, bool lockoutOnFailure)
        
            if (user == null)
            
                throw new ArgumentNullException(nameof(user));
            

            var error = await PreSignInCheck(user);
            if (error != null)
            
                return error;
            

            if (await UserManager.CheckPasswordAsync(user, password))
            
                var alwaysLockout = AppContext.TryGetSwitch("Microsoft.AspNetCore.Identity.CheckPasswordSignInAlwaysResetLockoutOnSuccess", out var enabled) && enabled;
                // Only reset the lockout when TFA is not enabled when not in quirks mode
                if (alwaysLockout || !await IsTfaEnabled(user))
                
                    await ResetLockout(user);
                

                return SignInResult.Success;
            
            Logger.LogWarning(2, "User userId failed to provide the correct password.", await UserManager.GetUserIdAsync(user));

PresigninCheck 和 CanSignUser 处理确认和锁定,您将在 UI 中收到不同于“无效登录尝试”的消息,并且还有一些日志:

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 可以返回导致 SignInResult.NotAllowed 的 fasle,但都带有日志记录:

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;
        

【讨论】:

仅供参考,我的浏览器填写了用户名和密码,因为它记住了它们。问题开始时我没有输入它们。似乎浏览器不太可能弄错。该应用程序能够发送电子邮件。 如果您输入错误,存储的密码可能是错误的。只有少数结果,您已排除锁定/确认。源代码在这里github.com/aspnet/Identity/blob/master/src/Identity/…。我意识到我太自信了,所以我更新了关于如何确认的答案。 但是当我输入它时它工作正常,直到现在浏览器为我填写它时它工作正常。由于这些原因,我相信这是正确的密码。即使不是这样,如果其他一切正常,忘记密码仍然可以使用。此外,我尝试查看输出控制台,但使用 Razor Pages,它没有显示相关消息。 如果您没有收到日志,则表示用户名错误,无法在数据库中找到。请看我的更新 我可以在数据库中看到我的用户名是正确的。您认为我在您的更新中遗漏了什么?

以上是关于登录到我的新 Razor Pages 应用程序时出现“无效登录”的主要内容,如果未能解决你的问题,请参考以下文章

Core Identity Razor Pages 或直接使用用户/角色/登录管理器

Razor Pages,表单页面处理程序不使用 GET 方法

ASP.NET Razor Pages 路由参数命名页面

ASP.net Core Razor Pages - 在代码隐藏中获取指定 div 的 HTML

Razor-Pages - HTML 标记

Razor Pages - 在所有 OnGet 处理程序之后从基类调用方法