You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 05:05:56