Wie löse ich eine AntiForgeryToken Ausnahme, die in meinem ASP.Net MVC-app nach einem Iisreset auftritt?

StackOverflow https://stackoverflow.com/questions/2206595

Frage

Ich habe Probleme mit dem AntiForgeryToken in ASP.Net MVC haben. Wenn ich ein iisreset auf meinem Web-Server tun und ein Benutzer weiterhin mit ihrer Sitzung sie auf eine Anmeldeseite erhalten prallt. Nicht schrecklich, aber dann wird die Fälschungs Token sprengt und der einzige Weg, wieder in Gang zu bringen, um den Cookie auf dem Browser wegzublasen.

Mit der Beta-Version von Version 1 früher falsch gehen, wenn das Cookie Lesen wieder in für mich so habe ich es zu schrubben, bevor eine Bestätigung fragen Token aber das wurde behoben, wenn es veröffentlicht wurde.

Im Moment denke ich, ich werde meinen Code rollen zurück, die das Beta-Problem behoben, aber ich kann nicht umhin zu denken, ich etwas fehle. Gibt es eine einfachere Lösung, Teufel sollte ich fallen nur ihre Helfer und erstellen Sie eine neue von Grund auf neu? Ich habe das Gefühl, dass eine Menge des Problems ist die Tatsache, dass es so tief in die alte ASP.Net Pipeline gebunden ist und versucht, es in Flickschusterei etwas zu tun, es war nicht wirklich entworfen zu tun.

hatte ich einen Blick in den Quellcode für die ASP.Net MVC 2 RC und es sieht nicht wie der Code viel geändert hat, so, während ich es nicht versucht haben, das glaube ich nicht, es gibt es keine Antworten .

Hier ist der relevante Teil des Stack-Trace der Ausnahme.

Edit: Ich erwähnte ich nicht nur klar, dass dies nur versucht, das Token auf der GET-Anforderung einzufügen. Dies ist nicht die Validierung, die auftritt, wenn Sie eine POST tun Tritte aus.

System.Web.Mvc.HttpAntiForgeryException: A required anti-forgery token was not
supplied or was invalid.
---> System.Web.HttpException: 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.
---> System.Web.UI.ViewStateException: Invalid viewstate. 
  Client IP: 127.0.0.1
  Port: 4991
  User-Agent: scrubbed
  ViewState: scrubbed
  Referer: blah
  Path: /oursite/Account/Login
---> System.Security.Cryptography.CryptographicException: Padding is invalid and
cannot be removed.
at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)
at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo)
at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError)
at System.Web.UI.ViewStateException.ThrowMacValidationError(Exception inner, String persistedState)
at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState)
at System.Web.Mvc.AntiForgeryDataSerializer.Deserialize(String serializedToken)
--- End of inner exception stack trace ---
at System.Web.Mvc.AntiForgeryDataSerializer.Deserialize(String serializedToken)
at System.Web.Mvc.HtmlHelper.GetAntiForgeryTokenAndSetCookie(String salt, String domain, String path)
at System.Web.Mvc.HtmlHelper.AntiForgeryToken(String salt, String domain, String path)
War es hilfreich?

Lösung

Wenn Ihr MachineKey gesetzt ist Ihre Überprüfung Token automatisch zu generieren, dann usw. wird ein Neustart der Anwendung nicht überleben -. ASP.NET einen neuen Schlüssel erzeugen, wenn er startet, und dann richtig die Token nicht zu entschlüsseln, werden in der Lage

Wenn Sie dies viel sehen, würde ich vorschlagen:

  1. eine statische MachineKey konfigurieren (Sie sollten diese auf der Anwendungsebene in der Lage zu tun) finden Sie unter " Gewusst wie: Konfigurieren eines MachineKey " für weitere Informationen
  2. Versuchen Sie nicht IIS Resets durchzuführen, wenn die Website verwendet wird 1

1 Der beste Weg, dies zu tun ist durch eine lastausgeglichenen Anwendung ist, die Sie benötigen eine statische MachineKey einzustellen. Eine weitere Möglichkeit ist die Website herunterzunehmen, indem Sie eine Datei mit dem Namen app_offline.htm in der Wurzel der Website platzieren, die die Site offline nehmen und Ihre Nachricht angezeigt werden -. Zumindest die Benutzer Dinge erwarten, falsch gehen

Andere Tipps

Für jetzt habe ich mit einer Lösung gegangen, die das Cookie schrubbt, wenn die Ausnahme ausgelöst wird. Wenn die Ausnahme ausgelöst wird wieder werde ich lass es einfach passieren, wie es war.

Ich werde markiere dies nicht als ‚die‘ Antwort jetzt in der Hoffnung, dass jemand eine bessere Antwort hat.

public static class MyAntiForgeryExtensions
{
    // Methods
    public static string MyAntiForgeryToken(this HtmlHelper helper)
    {
        return MyAntiForgeryToken(helper, null);
    }

    public static string MyAntiForgeryToken(this HtmlHelper helper, string salt)
    {
        string fragment;
        string path = helper.ViewContext.HttpContext.Request.ApplicationPath;
        try
        {
            fragment = helper.AntiForgeryToken(salt, null, path);
        }
        catch (HttpAntiForgeryException)
        {
            // okay, scrub the cookie and have another go.
            string cookieName = GetAntiForgeryTokenName(path);
            helper.ViewContext.HttpContext.Request.Cookies.Remove(cookieName);
            fragment = helper.AntiForgeryToken(salt, null, path);
        }
        return fragment;
    }

    #region AntiForgeryData code that shouldn't be sealed
    // Copied from AntiForgeryData since they aren't accessible.
    internal static string GetAntiForgeryTokenName(string appPath) {
        if (String.IsNullOrEmpty(appPath)) {
            return "__RequestVerificationToken";
        }
        else {
            return "__RequestVerificationToken_" + Base64EncodeForCookieName(appPath);
        }
    }
    private static string Base64EncodeForCookieName(string s) {
        byte[] rawBytes = Encoding.UTF8.GetBytes(s);
        string base64String = Convert.ToBase64String(rawBytes);

        // replace base64-specific characters with characters that are safe for a cookie name
        return base64String.Replace('+', '.').Replace('/', '-').Replace('=', '_');
    }
    #endregion
}

Ich hatte dieses Problem und zu reparieren, was Sie tun müssen, ist einen expliziten Computerschlüssel in Ihrem web-config ...

<machineKey validationKey="D82960E6B6E9B9029D4CAB2F597B5B4AF631E3C182670855D25FBDE1BFAFE19EFDE92ABBD1020FC1B2AE455D5B5F8D094325597CE1A7F8B15173407199C85A16" decryptionKey="577404C3A13F154908D7A5649EEC8D7C8A92C35A25A3EC078B426BB09D426A71" validation="SHA1" decryption="AES" /> 

sicherzustellen, seine platziert in web.config innerhalb ...

<system.web>

Sie können AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in global.asax hinzufügen

protected void Application_Start() {
    AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;
}
  

Wenn ich ein iisreset auf meinem Web-Server   und ein Benutzer weiterhin mit ihrem   Sitzung erhalten sie zu einem Login prallt   Seite.

Es gibt keinen Grund, ein Iisreset die Benutzer auf die Login-Seite zu bringen. Wenn Sie Cookies verwenden Authentifizierungsinformationen zu verfolgen und eine stateless Anwendung haben, sollte der Benutzer auch nach einem Neustart des Servers authentifiziert bleiben (natürlich, wenn eine Anforderung während des Resets gemacht wird, wird es nicht).

Eigentlich fand ich dies in meiner Anmelde Aktion zu arbeiten:

    public ActionResult LogOn()
    {
        formsAuthentication.SignOut();

        Response.Cookies.Clear();

        Session[SessionKeys.USER_SESSION_KEY] = null;
        Session.Clear();
        Session.Abandon();


        return View();
    }

Der wichtige Teil war: Response.Cookies.Clear ();

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top