如何调试 DNN 中的视图状态验证错误?

How to debug a viewstate validation error in DNN?

我有一个我继承的 DotNetNuke 应用程序,我正在尝试对现有模块进行一些更新。它恰好是一个自定义登录模块。

我正在尝试集成 2 因素身份验证。登录本身有效,但是当我之后想显示 2 个因素字段时,我在提交 2 个因素代码时收到 503 错误。

我试图在 global.asax 中添加一个 Application_Error 事件,但从未成功。我还尝试覆盖登录控件的 OnError 事件,但也从未命中。

在产生 503 的回发期间总是命中 OnInit,而不是 OnLoad。最奇怪的是,如果我跨过 OnInit 的每一行,直到我点击 OnInit 之外的第一件事,然后单击继续,一切正常。如果我只是从 OnInit 开头的断点单击继续,它几乎每次都会在到达 OnLoad 之前失败并显示 503。

这指向某种异步错误,但我无法想象它可能是什么。

如果有任何区别,面板控件会显示和隐藏登录与 2 个因素字段。

返回 503 错误的消息是 "No sites currently exist for this installation."

非常感谢任何有关如何缩小导致 503 的原因的建议。

更新

我错过了一个视图状态验证异常的日志条目。

Validation of viewstate MAC failed. If this application is hosted by a Web
Farm or cluster, ensure that configuration specifies the same validationKey 
and validation algorithm. AutoGenerate cannot be used in a cluster. 
See http://go.microsoft.com/fwlink/?LinkID=314055 for more information.

我设置了机器键值,但我仍然得到同样的错误。更不用说它也不能解释为什么只有在我不通过 OnInit

时才会发生这种情况

有什么想法吗?

事实证明,我的问题源于在尝试验证 2 因素身份验证之前调用 UserController.UserLogin()

现在我在 2 因素验证之后调用它,一切都按预期工作,甚至始终如一 :o)

代码

这是更改内容的示例。

这是无效的:

private void ValidateUser(UserInfo objUser, bool ignoreExpiring)
{
    UserValidStatus validStatus = UserValidStatus.VALID;
    string strMessage = Null.NullString;
    DateTime expiryDate = Null.NullDate;
    bool okToShowPanel = true;

    validStatus = UserController.ValidateUser(objUser, PortalId, ignoreExpiring);

    if (PasswordConfig.PasswordExpiry > 0)
    {
        expiryDate = objUser.Membership.LastPasswordChangeDate.AddDays(PasswordConfig.PasswordExpiry);
    }
    UserId = objUser.UserID;

    //Check if the User has valid Password/Profile
    switch (validStatus)
    {
        case UserValidStatus.VALID:
            //check if the user is an admin/host and validate their IP
            if (Host.EnableIPChecking)
            {
                bool isAdminUser = objUser.IsSuperUser || PortalSettings.UserInfo.IsInRole(PortalSettings.AdministratorRoleName); ;
                if (isAdminUser)
                {
                    if (IPFilterController.Instance.IsIPBanned(Request.UserHostAddress))
                    {
                        new PortalSecurity().SignOut();
                        AddModuleMessage("IPAddressBanned", ModuleMessage.ModuleMessageType.RedError, true);
                        okToShowPanel = false;
                        break;
                    }
                }
            }

            //Set the Page Culture(Language) based on the Users Preferred Locale
            if ((objUser.Profile != null) && (objUser.Profile.PreferredLocale != null))
            {
                Localization.SetLanguage(objUser.Profile.PreferredLocale);
            }
            else
            {
                Localization.SetLanguage(PortalSettings.DefaultLanguage);
            }

            //Set the Authentication Type used 
            AuthenticationController.SetAuthenticationType(AuthenticationType);

            var userRequestIPAddress = new UserRequestIPAddressController();
            //Complete Login
            UserController.UserLogin(PortalId, objUser, PortalSettings.PortalName, userRequestIPAddress.GetUserRequestIPAddress(new HttpRequestWrapper(Request)), RememberMe);

            var twoFactorAuthStatus = GetTwoFactorAuthStatus(objUser);

            switch (twoFactorAuthStatus)
            {
                case TwoFactorAuthStatus.Error:
                    return;
                case TwoFactorAuthStatus.NotEnabled:
                    RedirectUser(objUser);
                    break;
                case TwoFactorAuthStatus.SetupNeeded:
                    PageNo = googleAuthSetupPageNo;
                    break;
                case TwoFactorAuthStatus.VerificationNeeded:
                    PageNo = verifyGoogleAuthPageNo;
                    break;
            }
            break;
        case UserValidStatus.PASSWORDEXPIRED:
            strMessage = string.Format(Localization.GetString("PasswordExpired", LocalResourceFile), expiryDate.ToLongDateString());
            AddLocalizedModuleMessage(strMessage, ModuleMessage.ModuleMessageType.YellowWarning, true);
            PageNo = passwordPageNo;
            pnlProceed.Visible = false;
            break;
        case UserValidStatus.PASSWORDEXPIRING:
            strMessage = string.Format(Localization.GetString("PasswordExpiring", LocalResourceFile), expiryDate.ToLongDateString());
            AddLocalizedModuleMessage(strMessage, ModuleMessage.ModuleMessageType.YellowWarning, true);
            PageNo = passwordPageNo;
            pnlProceed.Visible = true;
            break;
        case UserValidStatus.UPDATEPASSWORD:
            AddModuleMessage("PasswordUpdate", ModuleMessage.ModuleMessageType.YellowWarning, true);
            PageNo = passwordPageNo;
            pnlProceed.Visible = false;
            break;
        case UserValidStatus.UPDATEPROFILE:
            //Save UserID in ViewState so that can update profile later.
            UserId = objUser.UserID;

            //When the user need update its profile to complete login, we need clear the login status because if the login is from
            //3rd party login provider, it may call UserController.UserLogin because they doesn't check this situation.
            new PortalSecurity().SignOut();
            //Admin has forced profile update
            AddModuleMessage("ProfileUpdate", ModuleMessage.ModuleMessageType.YellowWarning, true);
            PageNo = profilePageNo;
            break;
    }
    if (okToShowPanel) ShowPanel();
}

这是有效的方法:

private void ValidateUser(UserInfo objUser, bool ignoreExpiring)
{
    UserValidStatus validStatus = UserValidStatus.VALID;
    string strMessage = Null.NullString;
    DateTime expiryDate = Null.NullDate;
    bool okToShowPanel = true;

    validStatus = UserController.ValidateUser(objUser, PortalId, ignoreExpiring);

    if (PasswordConfig.PasswordExpiry > 0)
    {
        expiryDate = objUser.Membership.LastPasswordChangeDate.AddDays(PasswordConfig.PasswordExpiry);
    }
    UserId = objUser.UserID;

    //Check if the User has valid Password/Profile
    switch (validStatus)
    {
        case UserValidStatus.VALID:
            //check if the user is an admin/host and validate their IP
            if (Host.EnableIPChecking)
            {
                bool isAdminUser = objUser.IsSuperUser || PortalSettings.UserInfo.IsInRole(PortalSettings.AdministratorRoleName); ;
                if (isAdminUser)
                {
                    if (IPFilterController.Instance.IsIPBanned(Request.UserHostAddress))
                    {
                        new PortalSecurity().SignOut();
                        AddModuleMessage("IPAddressBanned", ModuleMessage.ModuleMessageType.RedError, true);
                        okToShowPanel = false;
                        break;
                    }
                }
            }

            var twoFactorAuthStatus = GetTwoFactorAuthStatus(objUser);

            switch (twoFactorAuthStatus)
            {
                case TwoFactorAuthStatus.Error:
                    return;
                case TwoFactorAuthStatus.NotEnabled:
                    LoginUser(objUser);
                    break;
                case TwoFactorAuthStatus.SetupNeeded:
                    PageNo = googleAuthSetupPageNo;
                    break;
                case TwoFactorAuthStatus.VerificationNeeded:
                    PageNo = verifyGoogleAuthPageNo;
                    break;
            }
            break;
        case UserValidStatus.PASSWORDEXPIRED:
            strMessage = string.Format(Localization.GetString("PasswordExpired", LocalResourceFile), expiryDate.ToLongDateString());
            AddLocalizedModuleMessage(strMessage, ModuleMessage.ModuleMessageType.YellowWarning, true);
            PageNo = passwordPageNo;
            pnlProceed.Visible = false;
            break;
        case UserValidStatus.PASSWORDEXPIRING:
            strMessage = string.Format(Localization.GetString("PasswordExpiring", LocalResourceFile), expiryDate.ToLongDateString());
            AddLocalizedModuleMessage(strMessage, ModuleMessage.ModuleMessageType.YellowWarning, true);
            PageNo = passwordPageNo;
            pnlProceed.Visible = true;
            break;
        case UserValidStatus.UPDATEPASSWORD:
            AddModuleMessage("PasswordUpdate", ModuleMessage.ModuleMessageType.YellowWarning, true);
            PageNo = passwordPageNo;
            pnlProceed.Visible = false;
            break;
        case UserValidStatus.UPDATEPROFILE:
            //Save UserID in ViewState so that can update profile later.
            UserId = objUser.UserID;

            //When the user need update its profile to complete login, we need clear the login status because if the login is from
            //3rd party login provider, it may call UserController.UserLogin because they doesn't check this situation.
            new PortalSecurity().SignOut();
            //Admin has forced profile update
            AddModuleMessage("ProfileUpdate", ModuleMessage.ModuleMessageType.YellowWarning, true);
            PageNo = profilePageNo;
            break;
    }
    if (okToShowPanel) ShowPanel();
}

我将第一个示例中的 RedirectUser() 更改为同样执行重定向的 LoginUser()LoginUser() 也会在成功的 2 因素身份验证 and/or 设置后调用。

一般来说,这是一种更安全的处理方式。我收到的调试反馈只是 super 令人沮丧的误导。