Подтвердить что ты не робот

Как решить исключение AntiForgeryToken, которое происходит после iisreset в моем приложении ASP.Net MVC?

У меня возникают проблемы с AntiForgeryToken в ASP.Net MVC. Если я сделаю iisreset на своем веб-сервере и пользователь продолжит свою сессию, они будут отскакивать на страницу входа. Не страшно, но тогда токен AntiForgery взорвется, и единственный способ вернуться - это снести куки файлы в браузере.

С бета-версией версии 1 она испортилась при чтении файла cookie для меня, поэтому я использовал его для очистки, прежде чем просить токен проверки, но это было исправлено, когда оно было выпущено.

На данный момент я думаю, что я вернусь к моему коду, который исправил проблему с бета-версией, но я не могу помочь, но думаю, что я что-то пропустил. Есть ли более простое решение, черт возьми, я должен просто бросить помощника и создать новый с нуля? У меня возникает ощущение, что большая проблема заключается в том, что он так глубоко привязан к старому конвейеру ASP.Net и пытается клонировать его, делая что-то, чего он не собирался делать.

Я просмотрел исходный код для ASP.Net MVC 2 RC, и это не похоже на то, что код сильно изменился, поэтому пока я его не пробовал, я не думаю, что есть ответы на него.

Вот соответствующая часть трассировки стека исключения.

Изменить: Я просто понял, что не упомянул, что это просто попытка вставить маркер в запрос GET. Это не проверка, которая возникает, когда вы запускаете POST.

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)
4b9b3361

Ответ 1

Если ваш MachineKey установлен в AutoGenerate, то ваши токены проверки и т.д. не смогут пережить перезапуск приложения - ASP.NET будет генерировать новый ключ при запуске, а затем не сможет правильно дешифровать маркеры.

Если вы видите это много, я бы предложил:

  • Настройка статического MachineKey (вы должны это сделать на уровне приложения), см. "Как настроить MachineKey" для Дополнительная информация
  • Не пытайтесь выполнять сброс IIS при использовании сайта 1

1 Лучший способ сделать это - иметь загруженное приложение, которое потребует установки статического MachineKey. Другим вариантом является удаление сайта, поместив в корневом каталоге файл с именем app_offline.htm, который отключит сайт и отобразит ваше сообщение. По крайней мере, пользователи будут ожидать, что что-то пойдет не так.

Ответ 2

На данный момент я пошел с решением, которое счищает куки файл, если исключение выбрано. Если исключение будет выброшено снова, я просто позволю этому случиться, как было.

Я не буду отмечать это как "ответ" на данный момент в надежде, что у кого-то будет лучший ответ.

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
}

Ответ 3

У меня была эта проблема, и чтобы исправить то, что вам нужно сделать, это добавить явный машинный ключ в вашу веб-конфигурацию...

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

обеспечить его размещение в web.config внутри...

<system.web>

Ответ 4

Вы можете добавить AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; в global.asax

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

Ответ 5

Если я делаю iisreset на своем веб-сервере и пользователь продолжает сессии они получают отскакивание от входа стр.

Нет причин для iisreset, чтобы привести пользователя на страницу входа. Если вы используете файлы cookie для отслеживания информации об аутентификации и используете приложение без учета состояния, пользователь должен пройти аутентификацию даже после перезагрузки сервера (конечно, если запрос выполняется во время reset, он не будет работать).

Ответ 6

На самом деле я нашел, что это работает в моем действии входа:

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

        Response.Cookies.Clear();

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


        return View();
    }

Важная часть: Response.Cookies.Clear();