如何调试 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 令人沮丧的误导。
我有一个我继承的 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 令人沮丧的误导。