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

Как сохранить измененный контент формы при выходе и возвращении на страницу HTTPS? (работает с HTTP)

  • Введите/измените что-то в текстовом поле
  • Перед отправкой формы оставьте страницу (например, нажав кнопку "Назад" ).
  • Вернитесь на страницу редактирования (например, нажав кнопку "вперед" ).

Ожидаемый результат: содержимое, указанное в текстовом поле, должно быть еще

Фактический результат:

  • с HTTPS: все изменения ушли (плохие!)
  • с HTTP: изменения все еще существуют (хорошо!)

Почему это происходит при использовании HTTPS? Как я могу это предотвратить? Ответен ли браузер или веб-сайт?

4b9b3361

Ответ 1

Вы можете рассмотреть следующие решения:

Атрибут autocomplete (HTML5)

Это кажется несвязанным, поскольку autocomplete сообщает браузеру о заполнении полей значениями на основе более раннего пользовательского ввода, которые были "отправлены" с формой. Но в моих тестах я увидел это; после заполнения формы без отправки; когда я нажимаю кнопку вперед (история) и снова ударяю; поля формы были автоматически заполнены, если я установил autocomplete="on", и все были очищены, если установлено значение "off".

Итак, (если они предназначены для пользователей HTML5), вы можете использовать этот атрибут для "кеширования" данных формы. (Работает во всех основных браузерах, кроме Opera).

<form action="/update" method="post" autocomplete="on">
    Email:    <input type="text" id="email" /><br />
    Username: <input type="text" id="uname" /><br />
    Password: <input type="password" id="pwd" autocomplete="off"/><br />
    <input type="submit" />
</form> 

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

MSDN Примечания:

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

Сохранять данные незаправленной формы локально:

Вы можете хранить входные данные локально, прямо перед перенаправлением страницы или событием фокуса для каждого элемента управления формой:

Cookies

В этом случае добрые старые куки могут пригодиться, но вы должны рассмотреть нижние стороны:

  • Даже если вы можете шифровать значения программно; поскольку мы будем работать на стороне клиента, файлы cookie для этого не являются действительно безопасными. Http-Only и Secure отмеченные файлы cookie не помогут нам здесь, потому что эти параметры используются для обеспечения SSL, когда cookie "отправляется" (защищен) и не может быть доступен из Javascript (только http).
  • У браузеров ограничение размера файлов cookie. От MSDN: "Поддержка большинства браузеров файлы cookie до 4096 байт. Из-за этого небольшого ограничения файлы cookie лучше всего использовать для хранения небольших объемов данных ". Итак, если вы не следите за этим размером (когда вы пишете файл cookie и/или ограничиваете контрольное значение через атрибуты maxlength); это может быть проблема. (и обрезка значения является наихудшей в этом случае).
  • Браузеры также имеют ограничение на количество файлов cookie, которые могут быть установлены. на домен. Так; при хранении данных формы в файлах cookie; вместо настройки файлов cookie для каждого значения поля формы; вы должны объединить их в одно или несколько файлов cookie; для вашего сайта не превышают этот предел.

Тем не менее, яркая сторона поддерживается всеми браузерами, и если вы не планируете "кэшировать" чувствительные и слишком длинные данные через Cookies, вы можете использовать следующее решение. Если это не так; вам лучше пойти со следующим предложением: localStorage.

// Below is just a demonstration and is not tested thoroughly for 
// production-ready web applications by any means.  
// But it should give you an idea.

/** 
 * Caches the user-input data from the targeted form, stores it in the cookies 
 * and fetches back to the form when requested or needed. 
 */
var formCache = (function () {
    var _form = null, 
        _formData = [],
        _strFormElements = "input[type='text'],"
                + "input[type='checkbox']," 
                + "input[type='radio']," 
                // + "input[type='password'],"  // leave password field out 
                + "input[type='hidden'],"
                // + "input[type='image'],"
                + "input[type='file'],"
                // more input types...
                + "input[type='email'],"
                + "input[type='tel'],"
                + "input[type='url'],"
                + "select,"
                + "textarea";

    function _warn() {
        console.log('formCache is not initialized.');
    }

    return {

        /**
         * Initializes the formCache with a target form (id). 
         * You can pass any container id for the formId parameter, formCache will 
         * still look for form elements inside the given container. If no form id 
         * is passed, it will target the first <form> element in the DOM. 
         */
        init: function (formId) {
            var f = (typeof formId === 'undefined' || formId === null || $.trim(formId) === '') 
                    ? $('form').first() 
                    : $('#' + formId);
            _form = f.length > 0 ? f : null;
            console.log(_form);
            return formCache; // make it chainable
        },

        /** 
         * Stores the form data in the cookies.
         */
        save: function () {
            if (_form === null) return _warn();

            _form
                .find(_strFormElements)
                .each(function() {
                    var f = $(this).attr('id') + ':' + formCache.getFieldValue($(this));
                    _formData.push(f);
                });
            docCookies.setItem('formData', _formData.join(), 31536e3); // 1 year expiration (persistent)
            console.log('Cached form data:', _formData);
            return formCache;
        },

        /** 
         * Fills out the form elements from the data previously stored in the cookies.
         */
        fetch: function () {
            if (_form === null) return _warn();

            if (!docCookies.hasItem('formData')) return;
            var fd = _formData.length < 1 ? docCookies.getItem('formData').split(',') : _formData;
            $.each(fd, function (i, item) {
                var s = item.split(':');
                var elem = $('#' + s[0]);
                formCache.setFieldValue(elem, s[1]);
            });
            return formCache;
        },

        /** 
         * Sets the value of the specified form field from previously stored data.
         */
        setFieldValue: function (elem, value) {
            if (_form === null) return _warn();

            if (elem.is('input:text') || elem.is('input:hidden') || elem.is('input:image') ||
                    elem.is('input:file') || elem.is('textarea')) {
                elem.val(value);
            } else if (elem.is('input:checkbox') || elem.is('input:radio')) {
                elem.prop('checked', value);
            } else if (elem.is('select')) {
                elem.prop('selectedIndex', value);
            }
            return formCache;
        },

        /**
         * Gets the previously stored value of the specified form field.
         */
        getFieldValue: function (elem) {
            if (_form === null) return _warn();

            if (elem.is('input:text') || elem.is('input:hidden') || elem.is('input:image') ||
                elem.is('input:file') || elem.is('textarea')) {
                    return elem.val();
                } else if (elem.is('input:checkbox') || elem.is('input:radio')) {
                    return elem.prop('checked');
                } else if (elem.is('select')) {
                    return elem.prop('selectedIndex');
                }
            else return null;
        },

        /**
         * Clears the cache and removes the previously stored form data from cookies.
         */
        clear: function () {
            _formData = [];
            docCookies.removeItem('formData');
            return formCache;
        },

        /**
         * Clears all the form fields. 
         * This is different from form.reset() which only re-sets the fields 
         * to their initial values.
         */
        clearForm: function () {
            _form
                .find(_strFormElements)
                .each(function() {
                    var elem = $(this);
                    if (elem.is('input:text') || elem.is('input:password') || elem.is('input:hidden') || 
                        elem.is('input:image') || elem.is('input:file') || elem.is('textarea')) {
                        elem.val('');
                    } else if (elem.is('input:checkbox') || elem.is('input:radio')) {
                        elem.prop('checked', false);
                    } else if (elem.is('select')) {
                        elem.prop('selectedIndex', -1);
                    }
                });
            return formCache;
        }
    };
})();

// Save form data right before we unload the form-page
$(window).on('beforeunload', function (event) {
    formCache.save();
    return false;
});

// Initialize and fetch form data (if exists) when we load the form-page back
$(document).on('ready', function (event) {
    formCache.init().fetch();
});

Вот рабочая версия на jsFiddle.

Примечание. "Код чтения/записи cookie" script от developer.mozilla.org должен быть включен в код выше. Вы также можете использовать Yahoo YUI 2: Cookie Utility, который имеет полезный метод setSub() для настройки под- cookie внутри одного файла cookie, для ограничения браузера, о котором я упоминал ранее.

LocalStorage

Вы также можете использовать более современные методы, такие как localStorage (HTML5). Это безопаснее и быстрее. Все основные браузеры поддерживают эту функцию, включая IE 8+. (Кроме того, поддержка iOS и Android!)

if (typeof Storage !== 'undefined') { // We have local storage support
    localStorage.username = 'Onur'; // to save to local storage
    document.getElementById('uname').value = localStorage.username; // to fetch from local storage
}

Итак, как в примере куки;

$(window).on('beforeunload', function (event) {
    saveFormToLocalStorage();
    return false;
});

$(document).on('ready', function (event) {
    fillFormFromLocalStorage()
});

SessionStorage

Это работает почти так же. Из W3C: объект sessionStorage равен объекту localStorage, за исключением того, что он хранит данные только для одного сеанса.

Сохранение данных формы на сервер/БД через Silent AJAX Post (s):

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

$(window).on('beforeunload', function (event) {
    //check if at least one field is filled out.
    //make the AJAX post if filled out.
    return "You are leaving the page without submitting the form...";
});

Получение ранее сохраненных данных с сервера при загрузке страницы:

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

Заключение

Если вам действительно нужно это и стоит проблемы; вы должны рассмотреть кросс-браузерное решение, которое реализует механизм возврата; например:

  • Если у вас есть поддержка функций HTML5; используйте HTML5 autocomplete атрибут. (Вы можете вставлять атрибут в HTML заранее или установите его через Javascript/jQuery, когда вы проверяете поддержку браузера.)
  • ELSE Если у вас есть поддержка объекта Storage; идти с localStorage
  • ELSE IF [файлы cookie текущих хранилищ] + [размер файла cookie формы данных] 4096 байт; затем используйте cookies.
  • ELSE Если у вас есть веб-приложение на стороне сервера, сделайте тихие запросы AJAX хранить данные на сервере.
  • ELSE этого не делает.

Примечание.. Для обнаружения функции HTML5 просмотрите эту страницу или эту страницу или вы можете использовать Modernizr.

Проблема с HTTPS:

Причина: все изменения формы исчезают при использовании HTTPS; это безопасный протокол . Формы в основном используются для ввода пользователем и могут (возможно) содержать конфиденциальные данные. Поэтому это поведение кажется естественным и ожидаемым. Решение (ы), которое я предлагаю выше, будет работать так же, как и для HTTP. Таким образом, это должно охватывать все ваши проблемы.

Дальнейшее чтение: