设置 ViewStateUserKey 给我一个“验证视图状态 MAC 失败”错误

问题描述 投票:0回答:6

我的

BasePage
类中有以下内容,我的所有 ASPX 页面均源自该类:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    ViewStateUserKey = Session.SessionID;
}

我还在

machineKey
中设置了
Web.config
。我不认为这个错误是由于网络场造成的,因为这也发生在我的开发机器上。

我的主机现已升级到.NET 3.5 SP1。在此更新之后,每次我使用上面的

ViewStateUserKey
设置进行编译时,我都会在每次回发时不断收到“验证视图状态 MAC 失败”错误。

我在这里做错了什么?最新的框架更新后,这个设置还有必要吗?

c# asp.net asp.net-2.0 viewstate failed-to-load-viewstate
6个回答
18
投票

好吧 - 我迟到了一年 - 但这是正确答案吗?这仅适用于经过身份验证的用户,并且使用

ViewStateUserKey
作为用户名比会话 ID GUID 更容易猜测。

顺便说一句,如果您想“修复”顶部的代码,请使用会话 ID,但是您必须设置一个会话变量,以便会话 ID 停止每次更改。前任。

Session["Anything"] = DateTime.Now

ViewStateUserKey = Session.SessionID;

这当然是假设您要使用会话,否则您需要使用其他一些密钥,例如用户名或保存在 cookie 中的任何其他 GUID。


9
投票

我进行了相当多的搜索以找到问题的确切原因。 Microsoft 的这篇文章确实有助于解释所有不同的原因。 http://support.microsoft.com/kb/2915218 原因 4 是我们发现的一个无效的 ViewStateUserKeyValue

将 ViewStateUserKey 设置为 Session.SessionID 或 User.Identity.Name 对我们来说不起作用。

由于以下原因,我们间歇性地收到验证错误。 当 IIS 重置应用程序池时,会话实际上会更新,从而导致错误。 我们在登录时删除会话以避免会话固定,这也会导致登录错误。

最终对我们有用的是基于 cookie 的解决方案,现在 VS2012 中提供了该解决方案。

public partial class SiteMaster : MasterPage
{
    private const string AntiXsrfTokenKey = "__AntiXsrfToken";
    private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
    private string _antiXsrfTokenValue;

    protected void Page_Init(object sender, EventArgs e)
    {
        //First, check for the existence of the Anti-XSS cookie
        var requestCookie = Request.Cookies[AntiXsrfTokenKey];
        Guid requestCookieGuidValue;

        //If the CSRF cookie is found, parse the token from the cookie.
        //Then, set the global page variable and view state user
        //key. The global variable will be used to validate that it matches in the view state form field in the Page.PreLoad
        //method.
        if (requestCookie != null
        && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
        {
            //Set the global token variable so the cookie value can be
            //validated against the value in the view state form field in
            //the Page.PreLoad method.
            _antiXsrfTokenValue = requestCookie.Value;

            //Set the view state user key, which will be validated by the
            //framework during each request
            Page.ViewStateUserKey = _antiXsrfTokenValue;
        }
        //If the CSRF cookie is not found, then this is a new session.
        else
        {
            //Generate a new Anti-XSRF token
            _antiXsrfTokenValue = Guid.NewGuid().ToString("N");

            //Set the view state user key, which will be validated by the
            //framework during each request
            Page.ViewStateUserKey = _antiXsrfTokenValue;

            //Create the non-persistent CSRF cookie
            var responseCookie = new HttpCookie(AntiXsrfTokenKey)
            {
                //Set the HttpOnly property to prevent the cookie from
                //being accessed by client side script
                HttpOnly = true,

                //Add the Anti-XSRF token to the cookie value
                Value = _antiXsrfTokenValue
            };

            //If we are using SSL, the cookie should be set to secure to
            //prevent it from being sent over HTTP connections
            if (FormsAuthentication.RequireSSL &&
            Request.IsSecureConnection)
            responseCookie.Secure = true;

            //Add the CSRF cookie to the response
            Response.Cookies.Set(responseCookie);
        }

            Page.PreLoad += master_Page_PreLoad;
        }

        protected void master_Page_PreLoad(object sender, EventArgs e)
        {
            //During the initial page load, add the Anti-XSRF token and user
            //name to the ViewState
            if (!IsPostBack)
            {
                //Set Anti-XSRF token
                ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;

                //If a user name is assigned, set the user name
                ViewState[AntiXsrfUserNameKey] =
                Context.User.Identity.Name ?? String.Empty;
            }
            //During all subsequent post backs to the page, the token value from
            //the cookie should be validated against the token in the view state
            //form field. Additionally user name should be compared to the
            //authenticated users name
            else
            {
                //Validate the Anti-XSRF token
                if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
                || (string)ViewState[AntiXsrfUserNameKey] !=
                (Context.User.Identity.Name ?? String.Empty))
            {
            throw new InvalidOperationException("Validation of
            Anti-XSRF token failed.");
            }
        }
    }
}

来源


3
投票

我现在通过将代码更改为来修复它:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    if (User.Identity.IsAuthenticated)
        ViewStateUserKey = User.Identity.Name;
}

2
投票

可以使用 EnableViewStateMac @Page 属性关闭 ViewState MAC 编码吗?


0
投票

非常奇怪,我也遇到了类似的问题三天,现在我解决了。 1.我启用了表单身份验证并且 ssl 为 false

<forms defaultUrl="~/" loginUrl="~/Account/Login.aspx" requireSSL="false" timeout="2880" />
  1. 但是在我的 httpcookies 标签中我有 requireSSL=true 。由于在 Site.Master.cs 中它使用 cookie 来设置 ViewStateUserKey,因此存在问题

  2. 因此我收到了错误。

  3. 我将其修改为 false 并重新启动网络应用程序,现在一切都很好。


0
投票

我知道这已经很旧了,但我想我会分享我如何解决我的问题。所以我修改的代码不是我的。我将跨站点脚本代码添加到我正在开发的应用程序和其他应用程序中。我遇到的问题是将提交操作更改为不同的页面。提交(在我的情况下)是不必要的,因此我将其从 form.submit() 更改为 window.location.href。问题解决了。

© www.soinside.com 2019 - 2024. All rights reserved.