Кнопка «Назад» в Safari и Chrome изменяет скрытые и отправляет значения в формах

Следующая проблема возникает как в Safari, так и в Chrome, поэтому, вероятно, проблема с WebKit.

Страница A: страница, для просмотра которой необходимо войти в систему, содержит форму с кнопкой type=submit, с name=submit и value=a

Страница B: какая-то другая страница

Страница C: попросите пользователя войти на страницу, содержит форму с кнопкой type=submit, с name=submit и value=c

Пользователь посещает страницу A, затем страницу B. Затем происходит бездействие, и время сеанса входа пользователя истекает. Пользователь нажимает кнопку «Назад», чтобы вернуться на страницу A. Браузер перенаправляет пользователя на страницу C.

В Safari и Chrome при отображении C форма на странице C имеет кнопку type=submit, name=submit, но значение отображается как «a».

Если вы перезагружаетесь на странице C, в качестве значения кнопки name=submit появляется «c».

Та же проблема возникает с полями ввода type=hidden; когда пользователь нажимает кнопку «Назад», их значения также изменяются на какое-то другое значение из какой-либо другой формы. Кроме того, эта проблема также проявляется без перенаправления, просто с отправкой, а затем обратно. В этом случае предыдущая страница отображается с неправильными значениями для скрытых и отправленных переменных CGI.

Пока единственное исправление, которое я могу придумать, - это использовать Javascript для сброса значений переменных type=hidden и type=submit после загрузки страницы C, чтобы убедиться, что значения верны. Но это не чисто и универсально применимо.

За исключением WebKit, исправляющего эту ошибку, кто-нибудь сталкивался с лучшим обходным путем?

Спасибо.


person OverClocked    schedule 03.03.2010    source источник
comment
мы экспериментируем с потенциальным обходным решением для этого, где мы делаем form.reset() при загрузке страницы. Если это сработает, я опубликую это как ответ, так как это более простой обходной путь.   -  person Archimedes Trajano    schedule 06.08.2020


Ответы (4)


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

Текущие браузеры на основе WebKit (по состоянию на 16.03.2010), например. Safari и Chrome обнаруживают следующие ошибки. Возможно, кто-то сможет взглянуть. Спасибо.

Ошибка 1: если на странице A есть несколько элементов формы F1 и F2, и в первой (в порядке появления в HTML) форме F1 автозаполнение отключено (т.е. ), а в F2 автозаполнение установлено на «включено». (поведение по умолчанию), затем после перехода со страницы A, а затем нажатия кнопки браузера «Назад», чтобы вернуться на страницу A, F1 и F2 могут быть автоматически заполнены неправильно. В частности, если F1 и F2 имеют элементы ввода с одинаковым именем и типом, скажем, N и T (т.е.), то при переходе обратно на страницу A с помощью кнопки «Назад» значение F1.N будет автоматически дополнено значением F2.N. .

Ошибка 2: сначала браузер открывает страницу A, а сервер возвращает HTML-страницу с элементами формы F1 и F2 (в обеих формах включено автозаполнение). Затем пользователь уходит со страницы А и впоследствии возвращается на страницу А с помощью кнопки «Назад» в браузере. При повторном посещении страницы A WebKit отправляет еще один запрос на сервер A (это отличается от поведения FireFox, когда при нажатии кнопки «Назад» серверу не отправляется запрос на добавление). Если сервер возвращает другую HTML-страницу (например, из-за выхода пользователя из сеанса) с элементами формы F3 и F4, которые отличаются от F1 и F2, но состоят из элементов ввода с тем же именем и типом, тогда F3 и F4 будут автозаполнение со значениями элемента ввода F1 и F2, даже для скрытого типа элемента ввода и отправки.

ОБХОД

Ошибка 1: никогда не используйте autocomplete="off", если вы не установили этот параметр для ВСЕХ форм на одной и той же HTML-странице.

Ошибка 2: конкретный случай, нет хорошего универсального решения. Мы нашли приемлемый обходной путь, включив скрытые формы, чтобы убедиться, что две версии страницы А имеют одинаковые формы; первая версия имеет F1, F2, F3, а вторая имеет F1, F2' и F3, где F2' — скрытая версия F2. Если мы не включим F2', то второй версией страницы A будет F1, F3 и F3, которые будут автоматически дополнены значениями элементов F2, даже для скрытых и отправленных элементов в F3.

АНАЛИЗ КОДА WebKit

Эти две ошибки встречаются в одной и той же части кода, но, вероятно, их можно рассматривать как две отдельные ошибки. Код находится в подкаталоге WebCore дерева кода WebKit.

Ошибка 1: в Document::formElementsState элементы ввода, у которых включено автозаполнение (проверено через HTMLInputElement::saveFormControlState), сохраняют свои состояния в векторе. Однако в HTMLFormControlElementWithState::finishParsingChildren каждый элемент формы, независимо от того, включено или выключено автозаполнение, восстанавливает состояние из вышеупомянутого вектора. Это приводит к ошибке 1.

Исправление ошибки 1: это должно быть довольно простым исправлением — finishParsingChildren не должен восстанавливать состояние, если для элемента отключено автозаполнение.

Отказ от ответственности: я не разрабатываю на Mac. Я только использую его, и мы разрабатываем веб-сайт. Я просто просматриваю код WebKit сегодня. Следовательно, я не создавал и не тестировал патч.

Ошибка 2. Это намного сложнее.

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

(мне тоже было бы интересно узнать об этом)

По сути, WebKit делает неверное предположение, что вторая выборка страницы А приводит к тому же HTML или, по крайней мере, к тому же набору форм, что и первая выборка. Если это не так, то логика автозаполнения больше не обеспечивает правильное/ожидаемое поведение.

Когда WebKit сохраняет состояние страницы, он вызывает Document::formElementsState, который просто создает карту пар и помещает в карту имя, тип и значение каждого входного элемента. Если два элемента ввода в двух разных формах имеют одинаковое имя и тип, сохраняются оба значения.

Например, скажем, страница A имеет формы F1 и F2, а F1 имеет элементы ввода с именами a1 и a2, с типами t1 и t2, со значениями v1 и v2 соответственно. F2 имеет входные элементы с именами a3 и a2, типами t1 и t2 и значениями v3 и v4 соответственно. WebKit сохраняет состояние этой страницы как (в нотации JSON)

{ "a1,t1" : [ v1 ], "a2,t2" : [ v2, v4 ], "a3,t1" : [ v3 ] }

Если пользователь повторно посещает страницу A с помощью кнопки «Назад» в браузере, WebKit попытается автоматически заполнить формы на новой версии страницы A, полученной с сервера, используя указанное выше состояние. Если новая версия страницы А имеет точно такие же формы, как и предыдущая, то все работает. Если нет, то WebKit ведет себя некорректно. Например, предположим, что при второй загрузке страницы A сервер возвращает только одну форму F3, а F3 имеет элементы ввода с именами a4 и a2, с типами t1 и t2, тогда элемент a2 F3 будет заполнен v2, сохраненным из предыдущего страница.

(Примечание: фактическая логика сохранения состояния и восстановления состояния, используемая в коде, немного отличается, но идея та же самая)

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

Исправление ошибки 2: это сложно, потому что WebKit повторно выбирает страницу A, когда пользователь нажимает кнопку «Назад». Если новая версия страницы A отличается от старой версии, WebKit не может легко сопоставить состояние формы из старой версии страницы с какой-либо формой, если она вообще существует, в новой версии. Вы не можете реально потребовать, чтобы все формы имели один и тот же идентификатор DOM, и даже если вы это сделаете, это все равно не совсем правильно, поскольку идентификаторы DOM должны быть уникальными в пределах HTML-страницы, но не должны быть уникальными для отдельных HTML-документов.

Единственное исправление, которое я могу придумать, заключается в следующем: когда вы сохраняете состояние при первом посещении страницы A, возьмите хэш страницы MD5 или SHA1 и сохраните его с состоянием элемента ввода. Когда вы вернетесь на страницу A, восстановите состояние только в том случае, если хэш MD5 или SHA1 тот же.

person OverClocked    schedule 16.03.2010

Я не уверен, но попробуйте добавить autocomplete = 'off' ко всем формам.

<form .... autocomplete = 'off'>
person a1ex07    schedule 03.03.2010
comment
Хорошая попытка, но не сработала. Если подумать, автозаполнение на самом деле предназначено для функции браузера, которая дополняет ваши формы вашими предыдущими ответами. Ошибка, которую я вижу, является результатом того, что Webkit пытается сохранить введенные пользователем данные на предыдущей странице, когда пользователь нажимает кнопку «Назад». - person OverClocked; 04.03.2010
comment
@ a1ex07: извините, ваше предложение почти верно. Вы должны отключить автозаполнение, и мой предыдущий комментарий о том, что автозаполнение похоже на автозаполнение, неверен. Это не. Но фишка в том, что вы должны отключить автозаполнение во ВСЕХ полях. Смотрите мой ответ на мой собственный вопрос. - person OverClocked; 17.03.2010
comment
У меня была проблема с очисткой Chrome значения некоторых скрытых входных данных, и добавление autocomplete='off' в форму решило ее. Спасибо! - person Felipe Castro; 20.10.2014

autocomplete="off"

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

DIV style="display:none"

и добавьте поля input_type="text" value="s" в тег DIV

person Sunder    schedule 09.07.2010
comment
display:none работал у меня в Google Chrome. Значение формы A, например. order_type="new" было неправильно помещено в форму B. Кто-то, отправляющий форму обновления B, будет иметь order_type="new", даже если фактический html (просмотреть исходный код) говорит order_type="up". Теперь я получаю странные результаты от Mobile Safari (Mozilla/5.0 (iPad; CPU OS 7_0_4, например Mac OS X) AppleWebKit/537.51.1 (KHTML, например Gecko) Version/7.0 Mobile/11B554a Safari/9537.53) В этом случае он должен есть order_id="new" или order_id="1". Когда они возвращаются, он автоматически заполняет их имя в поле order_id! - person Frank Forte; 04.12.2013

Одним из решений этой проблемы является сброс формы при загрузке документа.

function ready(fn) {
  if (document.readyState != 'loading'){
    fn();
  } else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}

function resetForm() {
   document.forms["myForm"].reset()
}
ready(resetForm)

person Archimedes Trajano    schedule 07.08.2020