ASP页面Azure B2C登录后自动提交表单失败及优化咨询
问题描述
原本的ASP登录页面包含用户名和密码表单,现在登录流程已切换为Azure B2C登录。目前通过JavaScript解析URL中的JWT令牌提取邮箱地址,填充到用户名字段后调用form.submit()提交表单触发后台登录方法,但表单未提交,页面停留在登录页。希望简化实现,直接完成登录并移除登录表单。
登录ASP页面代码
<%@ Control Language="C#" Inherits="LoginForm_Module" CodeFile="LoginForm.ascx.cs" %> <!-- «Start| Login Form» --> <asp:Panel runat="server" DefaultButton="btnLogin"> <script type="text/javascript"> function parseJwt() { var URIString = window.location.href; const myArray = URIString.split("="); var token = myArray[2]; var base64Url = token.split('.')[1]; var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); const obj = JSON.parse(jsonPayload); document.getElementById('Main_ctl01_txtEmail').value = obj.emails[1]; var form = document.getElementById("login_form"); form.submit(); return JSON.parse(jsonPayload); } </script> <body onload="javascript:parseJwt()"> <div class="form" id="login_form"> <span class="form-body"> <div class="item"> <span class="item-body"> <div class="input"> <asp:TextBox id="txtEmail" runat="server" CssClass='textbox' Text="" MaxLength="100"/> </div> </span> </div> <div class="item"> <span class="item-body"> <div class="input"> <asp:TextBox id="txtPassword" runat="server" TextMode="Password" AutoComplete="off" CssClass='textbox' Visible="false" MaxLength="100"/> </div> </span> </div> </span> <div class="buttons"> <asp:Button runat="server" ID="btnLogin" ValidationGroup="User" Text="Login" OnClick="btnLogin_Click"/> </div> </div> </body> </asp:Panel> <!-- «End| Login Form» -->
后台代码(Code Behind)
protected void btnLogin_Click(object sender, EventArgs e) { var user = User.FindByEmail(txtEmail.Text); if (user.IsLocked) { // Display the notification on the page: Controls.Add("<div class='account-locked-message'><span class='bold'>Your account has been locked.</span> Please contact PA Consulting on the following email to access your account again: <span class='bold'><a href='mailto:{0}'>{0}</a></span></div>".FormatWith(Settings.Current.ContactFormRecipientEmail)); return; } /* if (user != null && user.IsLocked) { // Display the notification on the page: Controls.Add("<div class='account-locked-message'><span class='bold'>Your account has been locked.</span> Please contact PA Consulting on the following email to access your account again: <span class='bold'><a href='mailto:{0}'>{0}</a></span></div>".FormatWith(Settings.Current.ContactFormRecipientEmail)); return; } if (user != null && user.Password != txtPassword.Text) { user.IncrementLoginRetryCount(); } if ((user == null || user.Password != txtPassword.Text)) { MessageBox.Show("Invalid username and/or password. Please try again."); return; } if (ShouldShowRecaptcha && !(new Recaptcha().Validate(Request))) { MessageBox.Show("There was an error in your Recaptcha response. Please try again."); return; } */ ImpersonationContext.Abort(); user.ResetLoginRetryCount(); user.AuditTrail(AuditableAction.LogIn); user.LogOn(); Response.Redirect(PageUrl("Login > Dispatch")); }
优化方案
1. 彻底移除表单,后台直接处理JWT
跳过前端解析和表单提交步骤,直接在后台页面加载时处理Azure B2C返回的令牌:
修改前端ASCX页面
删除所有表单和JS代码,仅保留服务器容器:
<%@ Control Language="C#" Inherits="LoginForm_Module" CodeFile="LoginForm.ascx.cs" %> <!-- Azure B2C 登录回调处理器 --> <asp:Panel runat="server" ID="pnlLoginHandler"> <!-- 无UI元素,仅后台逻辑处理 --> </asp:Panel>
修改后台Code Behind
在Page_Load事件中完成令牌解析、用户验证和登录:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 从URL获取Azure B2C返回的id_token(参数名根据实际回调配置调整) string token = Request.QueryString["id_token"]; if (!string.IsNullOrEmpty(token)) { try { // 解析JWT payload var payload = ParseJwtPayload(token); // 提取邮箱(注意:emails数组索引根据实际JWT结构调整) string email = payload["emails"] is JArray emails ? emails[1].ToString() : string.Empty; if (!string.IsNullOrEmpty(email)) { // 复用原登录逻辑 var user = User.FindByEmail(email); if (user == null) { MessageBox.Show("未找到该邮箱对应的账户,请联系管理员。"); return; } if (user.IsLocked) { Controls.Add("<div class='account-locked-message'><span class='bold'>您的账户已锁定。</span> 请联系PA Consulting获取帮助:<span class='bold'><a href='mailto:{0}'>{0}</a></span></div>".FormatWith(Settings.Current.ContactFormRecipientEmail)); return; } ImpersonationContext.Abort(); user.ResetLoginRetryCount(); user.AuditTrail(AuditableAction.LogIn); user.LogOn(); Response.Redirect(PageUrl("Login > Dispatch")); } else { MessageBox.Show("无法从登录令牌中获取邮箱信息,请重试。"); } } catch (Exception) { MessageBox.Show("登录令牌无效,请重新登录。"); } } else { MessageBox.Show("未获取到登录令牌,请重新通过Azure B2C登录。"); } } } // 后台JWT解析方法 private JObject ParseJwtPayload(string token) { var parts = token.Split('.'); if (parts.Length != 3) throw new ArgumentException("无效的JWT令牌"); string base64Url = parts[1]; string base64 = base64Url.Replace('-', '+').Replace('_', '/'); // 补全Base64填充字符 switch (base64.Length % 4) { case 2: base64 += "=="; break; case 3: base64 += "="; break; } string jsonPayload = Encoding.UTF8.GetString(Convert.FromBase64String(base64)); return JObject.Parse(jsonPayload); }
2. 临时修复原表单提交问题(若需保留现有逻辑)
如果暂时不想重构,先解决表单不提交的问题:
- 原代码中
login_form是<div>而非<form>标签,调用submit()无效,应触发ASP按钮的点击事件:// 替换form.submit()为以下代码 document.getElementById('<%= btnLogin.ClientID %>').click(); - 使用ASP.NET的
ClientID获取正确的前端元素ID,避免硬编码:document.getElementById('<%= txtEmail.ClientID %>').value = obj.emails[1];
内容的提问来源于stack exchange,提问作者Ian Smith
相关产品推荐
相关产品推荐

