Устранение проблем с анти-подделкой
У меня есть сообщение формы, которое постоянно дает мне токенную ошибку.
Вот моя форма:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.EditorFor(m => m.Email)
@Html.EditorFor(m => m.Birthday)
<p>
<input type="submit" id="Go" value="Go" />
</p>
}
Вот мой метод действия:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Join(JoinViewModel model)
{
//a bunch of stuff here but it doesn't matter because it not making it here
}
Вот машинаKey в файле web.config:
<system.web>
<machineKey validationKey="mykey" decryptionKey="myotherkey" validation="SHA1" decryption="AES" />
</system.web>
И вот ошибка, которую я получаю:
A required anti-forgery token was not supplied or was invalid.
Я читал, что изменение пользователей в HttpContext приведет к аннулированию токена, но этого здесь не происходит. HttpGet в моем действии Join просто возвращает представление:
[HttpGet]
public ActionResult Join()
{
return this.View();
}
Поэтому я не уверен, что происходит. Я искал вокруг, и все, кажется, предполагает, что это либо изменение машинного ключа (цикл приложения), либо изменение пользователя/сессии.
Что еще может быть? Как устранить эту проблему?
Ответы
Ответ 1
После помощи Адама, я получаю источник MVC, добавленный в мой проект, и смог увидеть, что есть много случаев, которые приводят к той же ошибке.
Вот метод, используемый для проверки токена анти-подделки:
public void Validate(HttpContextBase context, string salt) {
Debug.Assert(context != null);
string fieldName = AntiForgeryData.GetAntiForgeryTokenName(null);
string cookieName = AntiForgeryData.GetAntiForgeryTokenName(context.Request.ApplicationPath);
HttpCookie cookie = context.Request.Cookies[cookieName];
if (cookie == null || String.IsNullOrEmpty(cookie.Value)) {
// error: cookie token is missing
throw CreateValidationException();
}
AntiForgeryData cookieToken = Serializer.Deserialize(cookie.Value);
string formValue = context.Request.Form[fieldName];
if (String.IsNullOrEmpty(formValue)) {
// error: form token is missing
throw CreateValidationException();
}
AntiForgeryData formToken = Serializer.Deserialize(formValue);
if (!String.Equals(cookieToken.Value, formToken.Value, StringComparison.Ordinal)) {
// error: form token does not match cookie token
throw CreateValidationException();
}
string currentUsername = AntiForgeryData.GetUsername(context.User);
if (!String.Equals(formToken.Username, currentUsername, StringComparison.OrdinalIgnoreCase)) {
// error: form token is not valid for this user
// (don't care about cookie token)
throw CreateValidationException();
}
if (!String.Equals(salt ?? String.Empty, formToken.Salt, StringComparison.Ordinal)) {
// error: custom validation failed
throw CreateValidationException();
}
}
Моя проблема заключалась в том, что это условие, когда оно сравнивает имя пользователя Identity с именем пользователя токена формы. В моем случае у меня не было набора имен пользователей (один был пустым, другой - пустой).
Хотя я сомневаюсь, что многие столкнутся с таким же сценарием, мы надеемся, что другим будет полезно ознакомиться с основными условиями, которые проверяются.
Ответ 2
Я не знаю, имеете ли вы в виду, что вы можете получить ошибку по требованию - или вы видите ее в своих журналах, но в любом случае здесь можно гарантировать ошибку маркера antiforgery.
Подождите...
- Убедитесь, что вы вышли из системы, а затем введите свой логин
- Дважды нажмите кнопку входа в систему
- Вы получите:
Предоставленный токен анти-подделки предназначен для пользователя ", но текущий пользователь" [email protected]".
(На данный момент я предполагаю, что это точное сообщение об ошибке изменилось в MVC4 и что это по существу то же самое сообщение, которое вы получаете).
Там много людей, которые все еще дважды щелкают по всему - это плохо! Я просто понял это после того, как просто проснулся, так как это прошло через тестирование, которое я действительно не знаю. Вам даже не нужно дважды щелкнуть - у меня есть эта ошибка, когда я нажимаю второй раз, если кнопка не отвечает.
Я просто удалил атрибут проверки. Мой сайт всегда SSL, и я не слишком беспокоюсь о риске. Мне просто нужно, чтобы он работал прямо сейчас. Другим решением будет отключение кнопки с помощью javascript.
Это может быть дублировано на исходном шаблоне установки MVC4.
Ответ 3
Вам следует избегать подачи двойной формы.
Я предотвращаю этот тип проблемы, используя такой код:
$('#loginForm').on('submit',function(e){
var $form = $(this);
if (!$form.data('submitted') && $form.valid()) {
// mark it so that the next submit can be ignored
$form.data('submitted', true);
return;
}
// form is invalid or previously submitted - skip submit
e.preventDefault();
});
или
$('#loginForm').submit(function () {
$(this).find(':submit').attr('disabled', 'disabled');
});
Ответ 4
AntiForgeryToken также проверяет, что ваши зарегистрированные учетные данные пользователя не изменились - они также зашифрованы в файле cookie. Вы можете отключить это, установив AntiForgeryConfig.SuppressIdentityHeuristicChecks = true
в файле global.asax.cs.
Ответ 5
Я только что столкнулся с проблемой, когда @Html.AntiForgeryToken()
вызывается дважды, чтобы токен Anti-forger попадал в полезную нагрузку HTTP Post.
Ответ 6
Вы на одном сервере или веб-ферме? Если один сервер, закомментируйте свой элемент machineKey в файле web.config и повторите попытку в качестве базовой отправной точки. Любое изменение?
Кроме того, вы можете думать о каких-либо причинах, по которым ваши файлы cookie будут очищаться или истекают - они необходимы для того, чтобы это нормально работало.
Ответ 7
У меня также была такая же проблема, когда мне пришлось перенести мое приложение на новый компьютер. Я не мог понять, почему эта ошибка внезапно проявилась, но чувствовала, что она имеет какое-то отношение к миграции, поэтому начал исследовать регистрацию базы данных через aspnet_reqsql, когда это было устранено, я понял, что это должно быть связано с регистрацией приложения и, конечно же, я нашел ответ в подобном месте. Я также в своем путешествии обнаружил, что есть два способа решить это.
-
ASP.NET автоматически генерирует криптографический ключ для каждого приложения и сохраняет ключ в кусте реестра HKCU. Когда приложение переносится или открывается на ферме серверов, эти ключи не совпадают, поэтому первым методом является добавление уникального машинного ключа в файл web.config. Машинный ключ может быть сгенерирован с консоли управления IIS и добавлен в раздел вашего web.config
< MachineKey validationKey = "DEBE0EEF2A779A4CAAC54EA51B9ACCDED506DA2A4BEBA88FA23AD8E7399C4A8B93A006ACC1D7FEAEE56A5571B5AB6D74819CFADB522FEEB101B4D0F97F4E91" decryptionKey = "7B1EF067E9C561EC2F4695578295EDD5EC454F0F61DBFDDADC2900B01A53D4" проверка = "SHA1" дешифрование = "АЕС" /" >
-
Второй способ - предоставить доступ к реестру HKCU для рабочего процесса через appPool с использованием AspNet_RegIIS и switch -ga или для всех приложений с помощью -i
aspnet_regiis -ga "IIS APPPOOL\app-pool-name"
Какой бы метод вы ни выбрали, следует решить эту проблему, но, по моему мнению, самый надежный способ для будущих миграций и изменений в сервере будет уникальным ключом в web.config, учитывая, что это заставит приложение переопределить куст реестра HKCU и запустите приложение.
Ответ 8
Еще одна возможная вещь, чтобы проверить, вызвала ли эта ошибка для меня: у меня было две @Html.AntiForgeryToken()
в одной из моих форм.
Как только это было удалено, проблема исчезла.
Ответ 9
Необходимо проверить форму, она действительна, прежде чем отключить кнопку отправки.
<script type="text/javascript">
//prevent double form submission
$('form', '#loginForm').submit(function () {
if ($(this).valid()) {
$(this).find(':submit').attr('disabled', 'disabled');
}
});
Ответ 10
html error logger - неправильная строка.
вы должны проверить, что все значения загрузки на странице не равны нулю.