I have the following in my BasePage
class which all my ASPX pages derive from:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
ViewStateUserKey = Session.SessionID;
}
I also have a machineKey
set in Web.config
. I don't think this error is because of a web farm because this happens on my dev machine too.
My host has now upgraded to .NET 3.5 SP1. After this update, everytime I compile with the ViewStateUserKey
setting above, I constantly get the "Validation of viewstate MAC failed" error on every postback.
What am I doing wrong here? Is this setting even necessary anymore with the latest framework update?
Validation of viewstate MAC failed. If this application is hosted by a web farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
The error message is caused by some exception being thrown when the view state is being processed. The problem is that the exception is being consumed, and its details are lost in the error message. By using a debugger, you can determine the original exception.
The ViewState is a parameter specific to the ASP.NET framework, it's used as a breadcrumb trail when the user navigates the application preserving values and controls between different web pages. Present on the pages in the __viewstate parameter, all the values are serialized and encoded in base64 in a hidden field.
Setting the ViewStateUserKey property can help you prevent attacks on your application from malicious users. It does this by allowing you to assign an identifier to the view-state variable for individual users so that they cannot use the variable to generate an attack.
OK - Im a year late to the conversation - but how is this the correct answer? This applies only in the case of authenticated users and using the ViewStateUserKey
as the username is a lot easier to guess than a session id GUID.
BTW if you want to 'fix' the code up top, use the Session ID, however you must set a session variable in order for the session id to stop from changing every time. Ex.
Session["Anything"] = DateTime.Now
ViewStateUserKey = Session.SessionID;
This of course is assuming you are going to use sessions, otherwise you need some other key to use such as the username or any other guid kept in a cookie.
I've searched around quite a bit to find the definitive cause of the issue. This post from Microsoft really helped explain all the different causes. http://support.microsoft.com/kb/2915218 Cause 4 is what we have landed on which is an invalid ViewStateUserKeyValue
Setting ViewStateUserKey to Session.SessionID or User.Identity.Name did not work for us.
We intermittently got the validation error due to the following. When the application pool is reset by IIS, the session is renewed in effect causing the error. We drop the Session on login to avoid session fixation, also resulting in the error on login.
What finally worked for us was a cookie based solution, which is now provided in 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With