【问题标题】:Setting ViewStateUserKey gives me a "Validation of viewstate MAC failed" error设置 ViewStateUserKey 给我一个“视图状态 MAC 验证失败”错误
【发布时间】:2009-09-13 17:04:11
【问题描述】:

我的 BasePage 类中有以下内容,我的所有 ASPX 页面都来自这些:

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

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

我的主机现已升级到 .NET 3.5 SP1。此次更新后,每次我使用上述ViewStateUserKey 设置进行编译时,每次回发时都会不断收到“Validation of viewstate MAC failed”错误。

我在这里做错了什么?在最新的框架更新中是否还需要此设置?

【问题讨论】:

    标签: c# asp.net asp.net-2.0 viewstate failed-to-load-viewstate


    【解决方案1】:

    好的 - 我迟到了一年的谈话 - 但这是正确的答案吗?这仅适用于经过身份验证的用户并且使用 ViewStateUserKey 作为用户名比会话 ID GUID 更容易猜测。

    顺便说一句,如果您想在顶部“修复”代码,请使用会话 ID,但是您必须设置会话变量以使会话 ID 每次都停止更改。前任。 Session["Anything"] = DateTime.Now

    ViewStateUserKey = Session.SessionID;
    

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

    【讨论】:

    • 补充说明,有时我看到 sessionid 每次都在更改,直到使用会话,而其他时候会话 cookie 立即发送到客户端,而似乎没有使用会话。我还不是 100% 确定为什么会这样,但只是我注意到了。
    • 这很有帮助。我不知道如果其中没有保存任何内容,ASP 不会保持会话。
    【解决方案2】:

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

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

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

    最终对我们有用的是基于 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.");
                }
            }
        }
    }
    

    Source

    【讨论】:

    • 能否请您详细说明一下?不仅是链接
    • 解释了为什么其他解决方案不适合我们。并将代码示例放在帖子上。
    • 我目前正在尝试您的解决方案,目前看来效果不错。
    • 我没有深入检查,但我想知道 web.config 的可选部分 " 是否不符合我们的预期:)
    • 我对上述代码的主要问题是:我们不是通过将 AntiXsrfTokenKey 放到浏览器中并且从不更新它来做类似于会话固定的事情吗?给恶意用户这么多时间编织一个新的攻击性回发表单,它可以持续一年吗?
    【解决方案3】:

    我现在通过将代码更改为:

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
    
        if (User.Identity.IsAuthenticated)
            ViewStateUserKey = User.Identity.Name;
    }
    

    【讨论】:

    • @Druid 除了将上面的代码放在基页的 Oninit 事件中之外,我在这里也有同样的问题。我是否需要在任何子页面中设置 viewstateuserkey ..你能告诉我.. ..
    • @pratapk 据我记得,没必要每页都设置。
    【解决方案4】:

    你能用 EnableViewStateMac @Page 属性关闭 ViewState MAC 编码吗?

    【讨论】:

    • 是的,如果我这样做,它会起作用。如果没有用,我宁愿删除 ViewStateUserKey 设置...
    【解决方案5】:

    很奇怪,我也有类似的问题 3 天,现在我解决了。 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 并重新启动 web 应用程序,现在一切正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-11
      • 1970-01-01
      • 2010-09-24
      • 2011-12-18
      相关资源
      最近更新 更多