首页 > 解决方案 > 仅当从已空闲一段时间的移动浏览器发回时,“视图状态 MAC 验证失败”

问题描述

我知道这个问题在 StackOverflow 上经常被问到,但我的情况有点不同。我检查了与此问题相关的所有答案,但没有一个能解决我的问题,因为在我的情况下,它只发生在移动设备上的浏览器上。

从已打开一段时间的移动浏览器发回时,我只会收到“ViewState MAC 验证失败”错误。从计算机浏览器提交表单时,该错误永远不会出现。大多数情况下,从移动浏览器提交时,它都不会出现。它仅在我打开一段时间以来已提交的移动选项卡并再次单击提交按钮时出现。

但是,当我关闭浏览器(因此它不在移动后台运行)时,它也会一直发生,再次打开它并重新提交表单。我想这是此错误背后的主要问题(重新启动浏览器会导致在移动设备上重新加载页面,然后再单击任何内容)。


我尝试了以下解决方案,但都没有奏效:

  1. 手动将 MachineKey 设置为我的web.config
  2. 使用 aspnet_regiis 实用程序运行将保留机器密钥的托管应用程序。
  3. 本文提出的解决方案
  4. LoadUserProfile = True在应用程序池中设置
  5. 在 IIS 应用程序池中设置SessionTimeout = 0
  6. 通过 http 保护我的 cookie。

注意:我知道我的设置enableViewStateMac="false"web.config解决我的问题,但我真的不希望这样做以避免我的应用程序中的安全性贬值。


经过几次测试,我注意到该错误仅在移动浏览器强制重新加载/重新启动页面时产生。例如,如果我重新提交已经从手机提交的表单,大多数情况下它不会产生错误。但是,有时,当我在移动设备上打开浏览器时,它会在我单击任何内容之前强制重新加载/重新启动页面。现在,当我单击提交按钮时,会出现错误。

ViewState由于正在更改,因此此强制重新加载/重新启动可能会导致此错误。

另一种可能性是,即使我在 IIS 中将会话设置为不会过期,移动设备也会使会话过期。

然而,另一种可能性是移动设备不允许浏览器在后台运行,导致当用户再次打开浏览器时强制重新加载以重新构建页面。


我在我的应用程序中使用以下代码:

Partial Class MasterPage
    Inherits System.Web.UI.MasterPage

    Private Const AntiXsrfTokenKey As String = "__AntiXsrfToken"
    Private Const AntiXsrfUserNameKey As String = "__AntiXsrfUserName"
    Private _antiXsrfTokenValue As String

    Protected Sub Page_Init(sender As Object, e As EventArgs)
        ' The code below helps to protect against XSRF attacks
        Dim requestCookie = Request.Cookies(AntiXsrfTokenKey)
        Dim requestCookieGuidValue As Guid
        If requestCookie IsNot Nothing AndAlso Guid.TryParse(requestCookie.Value, requestCookieGuidValue) Then
            ' Use the Anti-XSRF token from the cookie
            _antiXsrfTokenValue = requestCookie.Value
            Page.ViewStateUserKey = _antiXsrfTokenValue
        Else
            ' Generate a new Anti-XSRF token and save to the cookie
            _antiXsrfTokenValue = Guid.NewGuid().ToString("N")
            Page.ViewStateUserKey = _antiXsrfTokenValue

            Dim responseCookie = New HttpCookie(AntiXsrfTokenKey) With {
                .HttpOnly = True,
                .Value = _antiXsrfTokenValue
            }
            If FormsAuthentication.RequireSSL AndAlso Request.IsSecureConnection Then
                responseCookie.Secure = True
            End If
            Response.Cookies.[Set](responseCookie)
        End If

        AddHandler Page.PreLoad, AddressOf master_Page_PreLoad
    End Sub

    Protected Sub master_Page_PreLoad(sender As Object, e As EventArgs)
        If Not IsPostBack Then
            ' Set Anti-XSRF token
            ViewState(AntiXsrfTokenKey) = Page.ViewStateUserKey
            ViewState(AntiXsrfUserNameKey) = If(Context.User.Identity.Name, [String].Empty)
        Else
            ' Validate the Anti-XSRF token
            If DirectCast(ViewState(AntiXsrfTokenKey), String) <> _antiXsrfTokenValue OrElse DirectCast(ViewState(AntiXsrfUserNameKey), String) <> (If(Context.User.Identity.Name, [String].Empty)) Then
                Throw New InvalidOperationException("Validation of Anti-XSRF token failed.")
            End If
        End If
    End Sub

    Private Sub MasterPage_Load(sender As Object, e As EventArgs) Handles Me.Load
       'Add Base Path and Canonical URL
        Dim strBasePath = "<base href='" & AppSettings("LivePath") & "' />"
        Page.Header.Controls.Add(New LiteralControl(strBasePath))
    End Sub
End Class

我希望有一个解决方案,因为我不想最终设置enableViewStateMac="false"在我的web.config


[更新]

潜在解决方案:

我目前对此的潜在解决方案是处理“ViewState MAC 验证失败”错误,并向用户提示自定义消息,解释表单验证失败。这样,安全性和可用性就得到了平衡。

我受到这篇文章的启发,因为这个可能是短暂的解决方案。

标签: asp.netvb.netwebformsviewstatemachinekey

解决方案


推荐阅读