2011-12-21 2 views
9

Im, использующий MVC 3, и все правильно настроено из того, что я вижу.Необходимый токен анти-подделки не был указан или был недействителен

Пользователь Authenticates отправляет форму с помощью токена AntiForgery и все работает нормально.

То есть, если пользователь не оставил открытую форму и в течение этого времени истек срок действия логина пользователя.

Когда пользователь отправляет форму, поскольку она больше не аутентифицирована, ее следует вернуть на страницу входа. (это случается несколько раз)

Вместо этого исключение «Необходимый токен анти-подделки не был указан или был недействителен». бросается. Я предполагаю, что его бросают, потому что зашифрованный токен содержит некоторые детали пользователя, которые не могут быть проверены, поскольку пользователь больше не аутентифицирован.

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

Эта проблема трудно реплицировать, так как она не всегда это делает.

Я вижу, что у многих людей такая проблема, но никаких решений не ожидается.

Это проблема в самом MVC?

Установка ключа машины и все в порядке, так что это не проблема.

+0

Анти-подделка фактически происходит в 'System.Web.WebPages', а не MVC. Поэтому вы хотели бы посмотреть в этом источнике, а не на MVC. –

+0

Я не уверен, что AntiForgeryToken имеет какое-либо отношение к пользователю, так как он может использоваться независимо от авторизации. Это может быть связано во времени. – stevethethread

ответ

2

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

В целом (игнорируя различные варианты) AntiForgeryToken работает, добавляя файл cookie сеанса, который затем читается, когда форма отправляется, украшая контроллер атрибутом [ValidateAntiForgeryToken].

Прежде всего, прежде чем мы начнем фиксировать что-либо в качестве общего правила, всегда делайте следующее.

  1. В web.config создайте машинуKey следующим образом.

    <machineKey validationKey="YOUR_KEY" decryptionKey="YOUR_KEY" validation="SHA1" decryption="AES" />

    ** Примечание SHA1 это то будет не действительно очень безопасный больше, но другое обсуждение **

    Google <machineKey> Generator и настройке.

    http://msdn.microsoft.com/en-us/library/w8h3skw9%28v=vs.100%29.aspx

  2. Изменить имя по умолчанию печенье от «__RequestVerificationToken» на тот, который будет не используется другим приложением. (Я всегда использую GUID).

    ли это с AntiForgeryConfig.CookieName = "YOUR_NAME";

  3. Создать новый пользовательский атрибут.

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

Еще одна проблема заключается в том, что если у вас есть атрибут [Авторизовать] на отправленном контроллере, поток вещей упустит исключение HttpAntiForgeryException, прежде чем он проверяет, кто является аутентифицированным. (в большинстве случаев проверки подлинности на основе файлов cookie, когда сеанс истек, пользователь больше не аутентифицирован)

Способ решения этого вопроса заключается в создании пользовательского атрибута [CustomValidateAntiForgeryToken].

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 
    public class CustomValidateAntiForgeryToken : FilterAttribute, IAuthorizationFilter { 

    public void OnAuthorization(AuthorizationContext filterContext) { 

     if (filterContext == null) { 
     throw new ArgumentNullException("filterContext"); 
     } 

     try { 
     AntiForgery.Validate(); 
     } 
     catch { 

     // Here do whatever is you wish 
     // you could just re throw the error or what ever. 

     // In this case I have redirected to a Signout 

     filterContext.Result = new RedirectToRouteResult( 
      new RouteValueDictionary( 
      new { 
       action  = "Sign_Out", 
       controller = "SOME_CONTROLLER", 
       area  = "" 
      } 
     ) 
     ); 

     } 

    } 

    } 

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

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

Если кто-либо видит что-либо, что поможет или может быть добавлено, пожалуйста, сделайте это.

1

На вашем Action положите атрибут [Authorize] над атрибутом [ValidateAntiForgeryToken]. Они выполняются по порядку сверху вниз. Таким образом, он должен нажать на авторизацию и увидеть, что вы больше не аутентифицированы.

+0

Атрибуты не гарантируются в том порядке, в котором вы их написали, не так ли? –

+0

Ryand.Johnson, это уже случай, хотя это не должно действительно вызвать проблему. –

5

Причина в том, что в некоторых крупных организациях люди оставляют свои машины включенными без перезапуска и открываются браузеры, не закрывая их очень долгое время. Иногда даже недели подряд.

Если ключ машины был добавлен позднее или изменен, те машины, которые не были отключены или были отключены браузером, являются причинами этой ошибки. После перезагрузки каждой машины или закрытия браузера ошибка остановится.

Примечание. Чтобы остановить эту ошибку, важно также создать машинный ключ.

Google: машина генератор ключей

+4

Я не знаю, почему это было проголосовано. Это именно то, что вызывало проблему у нас, и как только был добавлен машинный ключ, и все машины были перезагружены, проблема больше не возникала. –