我有一个使用.NET Identity框架的.NET Core MVC应用程序。直到最近,这一切都运行良好(并且已经持续了 18 个月(。
使用 IIS Express 在本地运行项目时,登录表单的提交只会在 Chrome 中挂起。灰色纺车出现在Chrome标签上,但没有任何反应。我已经在登录页面的代码中添加了一个断点(它是一个脚手架的 MVC Razor 页面(,但从未命中此断点。
我的网站的实时版本按预期工作,在 Firefox 本地运行时,它也可以正常工作并且命中断点。对我来说,这似乎是Chrome或IIS Express的问题?
我试过:
- Chrome 中的隐身模式。
- 清除 Cookie 和缓存对象。 在Visual Studio
- 2017和Visual Studio 2019中运行项目。
- 重新启动我的电脑。 重新启动VS
- 和Chrome。
下面是我的登录页面的代码和 HTML。如前所述,这是使用 Visual Studio 搭建的,因此除了使用 AWS Cognito 作为我的用户存储所需的更改之外,大部分内容都是标准内容。这些代码最近也没有改变。
登录.cshtml
@page
@model LoginModel
@{
ViewData["Title"] = "Log in";
}
<div class="container">
<h2>@ViewData["Title"]</h2>
<hr />
@if (Model.ModelState.ErrorCount > 0)
{
<div asp-validation-summary="All" class="alert alert-danger"></div>
}
<div class="row">
<div class="col-md-6">
<section>
<form method="post">
<div class="form-group">
<label asp-for="Input.Username"></label>
<input asp-for="Input.Username" class="form-control" />
<span asp-validation-for="Input.Username" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label asp-for="Input.RememberMe">
<input asp-for="Input.RememberMe" />
@Html.DisplayNameFor(m => m.Input.RememberMe)
</label>
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-default">Log in</button>
</div>
<div class="form-group">
<p>
<a asp-page="./ForgotPassword">Forgot your password?</a>
</p>
</div>
</form>
</section>
</div>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
登录.cshtml.cs
using Amazon.AspNetCore.Identity.Cognito;
using Amazon.Extensions.CognitoAuthentication;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Serilog;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using TAP.Web.Filters;
namespace TAP.Web.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class LoginModel : PageModel
{
private readonly UserManager<CognitoUser> userManager;
private readonly SignInManager<CognitoUser> signInManager;
private readonly ILogger logger;
public LoginModel(
UserManager<CognitoUser> userManager,
SignInManager<CognitoUser> signInManager,
ILogger logger)
{
this.userManager = userManager;
this.signInManager = signInManager;
this.logger = logger;
}
[BindProperty]
public InputModel Input { get; set; }
public IList<AuthenticationScheme> ExternalLogins { get; set; }
public string ReturnUrl { get; set; }
[TempData]
public string ErrorMessage { get; set; }
public class InputModel
{
[Required]
[Display(Name = "Username or Email")]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
public async Task OnGetAsync(string returnUrl = null)
{
if (!string.IsNullOrEmpty(ErrorMessage))
{
ModelState.AddModelError(string.Empty, ErrorMessage);
}
returnUrl = returnUrl ?? Url.Content("~/");
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme).ConfigureAwait(false);
ReturnUrl = returnUrl;
}
[TestFilter]
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var result = await signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberMe, lockoutOnFailure: false);
var user = await this.userManager.FindByIdAsync(Input.Username);
if (result.Succeeded)
{
logger.Information($"User logged in ({Input.Username}).");
return LocalRedirect(returnUrl);
}
else if (result.IsCognitoSignInResult())
{
if (result is CognitoSignInResult cognitoResult && cognitoResult.RequiresPasswordChange)
{
switch (user.Status)
{
case "FORCE_CHANGE_PASSWORD":
logger.Warning($"User password needs to be changed ({Input.Username}).");
return RedirectToPage("./ChangePassword", new { username = Input.Username, required = true });
case "RESET_REQUIRED":
logger.Warning($"User password needs to be reset ({Input.Username})");
ModelState.AddModelError(string.Empty, "Your password requires resetting. Please check your emails for the reset password link.");
break;
default:
break;
}
}
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
}
return Page();
}
// If we got this far, something failed, redisplay form
return Page();
}
}
}
我在使用localhost时遇到了完全相同的问题,并将其追溯到用于密码字段的数据类型。 如果我删除了"[DataType(DataType.Password(]",那么它不再挂起,尽管密码字段是公开的。
[Required]
//[DataType(DataType.Password)]
public string Password { get; set; }
我认为 Chrome 检测到您的字段是密码类型,并正在尝试提示更新或保存您的 Chrome 帐户密码列表中的密码。 由于某种原因,浏览器正在拦截并挂起。 当您移除数据类型修饰时,Chrome 不会将其视为密码类型,而是将邮件发送到服务器。
我注意到,只有当您填充空密码字段或完全更改整个密码时,它才会挂起 Chrome。 如果您修改(添加/更改/删除某些字符(密码而不替换整个内容,它似乎可以正常工作。
它也是最近才开始发生在我身上的。 是否有Chrome更新可能破坏了本地主机的密码存储? 很抱歉,我还没有一个明确的答案,但也许我们可以共同努力解决这个问题。
我会将其作为评论而不是答案发布,但我还没有 50 声誉。