Identity Framework登录OnPostAsync出现Error 400问题排查
问题诊断与修复方案
1. Error 400 & 断点未触发的核心原因:缺少CSRF防伪造令牌
ASP.NET Razor Pages默认会拦截未携带有效防伪造令牌的POST请求,你的登录表单中没有包含该令牌,第一次提交时可能因会话初始状态绕过验证,但第二次提交时令牌失效/缺失,请求直接被中间件拦截,根本没到达OnPostAsync方法,所以断点不会触发。
修复:添加防伪造令牌
在登录表单内添加令牌,两种方式任选其一:
- 直接注入令牌:
<form id="account" method="post"> @Html.AntiForgeryToken() <!-- 表单内容 --> </form>
- 使用Razor Pages表单标签助手(自动注入令牌):
<form id="account" method="post" asp-page="./Login"> <!-- 表单内容 --> </form>
2. 登录逻辑顺序颠倒
当前代码先执行登录成功操作,再检查账户是否封禁,这会导致封禁用户被标记为登录成功,之后又被强制返回页面,同时产生不必要的登录日志和连接时间更新。
修复:先验证账户状态,再执行登录
修改OnPostAsync逻辑:
public async Task<IActionResult> OnPostAsync(string returnUrl = null) { returnUrl ??= Url.Content("~/"); ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); if (ModelState.IsValid) { DetalleUsuarioDA detalleUsuarioDA = new DetalleUsuarioDA(); DetalleUsuario detalleUsuario = detalleUsuarioDA.GetDetalleUsuario(Input.Email); // 优先检查账户是否封禁 if (detalleUsuario != null && detalleUsuario.EstadoUsuario == "Bloqueado") { ModelState.AddModelError(string.Empty, "Invalid login attempt."); ViewData["showModalBloqueo"] = true; // 记录封禁登录尝试日志 RegistroDA registroDA = new RegistroDA(); Registro registro = new Registro(); registro.DescripcionRegistro = "Intento de inicio de sesión desde la ip: " + HttpContext.Connection.RemoteIpAddress + " - Cuenta bloqueada"; registro.Fk_Usuario = detalleUsuario.Fk_User; registro.TipoRegistro = "Advertencia"; registro.FechaRegistro = DateTime.Now; registro.Estado = "No leido"; registroDA.InsertRegistro(registro); return Page(); } // 账户正常,执行登录操作 var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false); if (result.Succeeded) { if (detalleUsuario != null) { detalleUsuario.UltimaConexion = DateTime.Now; detalleUsuarioDA.EditarDetalleUsuario(detalleUsuario); RegistroDA registroDA = new RegistroDA(); Registro registro = new Registro(); registro.DescripcionRegistro = "Hubo un inicio de sesión desde la ip: " + HttpContext.Connection.RemoteIpAddress; registro.Fk_Usuario = detalleUsuario.Fk_User; registro.TipoRegistro = "Notificación"; registro.FechaRegistro = DateTime.Now; registro.Estado = "No leido"; registroDA.InsertRegistro(registro); } _logger.LogInformation("User logged in."); return LocalRedirect(returnUrl); } // 其余登录失败分支逻辑 if (result.RequiresTwoFactor) { return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe }); } if (result.IsLockedOut) { _logger.LogWarning("User account locked out."); return RedirectToPage("./Lockout"); } else { ModelState.AddModelError(string.Empty, "Invalid login attempt."); return Page(); } } return Page(); }
3. "Recuerdame"复选框未绑定模型
当前复选框没有绑定到Input.RememberMe,导致该值永远为false,无法实现记住登录状态的功能。
修复:绑定复选框到模型属性
<div class="form-check mb-4"> <input class="form-check-input" type="checkbox" id="termsCheckbox" asp-for="Input.RememberMe"> <label class="form-check-label text-white" for="termsCheckbox"> Recuerdame </label> </div>
4. 模态框触发脚本兼容性问题
$(window).load()在jQuery 3.0+版本已被废弃,可能导致模态框无法正常弹出。
修复:替换为标准DOM就绪事件
<script> $(document).ready(function () { $('#modal_bloqueo').modal('show'); }) </script>
内容的提问来源于stack exchange,提问作者José David Perales Altamirano
相关产品推荐
相关产品推荐

