如何离开,回到HTTPS页面时,同步更改形式的内容? (与HTTP作品)(How to keep

2019-07-18 10:55发布

  1. 输入/改变的东西在一个textarea
  2. 提交表单前,离开页面(例如,通过点击浏览器的后退按钮)
  3. 返回到编辑页面(点击前进按钮EG)

预期结果:在textarea的输入内容仍然应该有

实际结果:

  • 使用HTTPS:所有的改变都不见了(坏!)
  • HTTP:变化仍然存在(好!)

为什么使用HTTPS,当这种情况发生? 我怎样才能避免这种情况? 是浏览器或网站负责?

Answer 1:

您可以考虑以下解决方案:

autocomplete属性(HTML5)

这似乎不相关的,因为autocomplete通知浏览器来完成与此基础上进行了“提交”与早期形式的用户输入的值的字段。 但在我的测试中,我看到了; 填写表格而不提交之后; 当我打前锋(历史)按钮,然后再次回击; 表单字段已自动填写,如果我设置autocomplete="on"并设置为当所有被清除了"off"

所以; (如果针对HTML5的用户),您可以使用该属性“缓存”的表单数据。 (适用于所有主要的浏览器,除了歌剧)。

<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备注:

  • 如果autocomplete属性丢失,现场将默认为“打开”状态,如果元素没有父窗体,或如果窗体有自动完成设置“开”到。
  • 通过自动完成功能提供的信息不被暴露于对象模型,直到用户选择的建议,文本字段的值,一个是不是一个网页可见。

本地保存未提交表单数据:

您可以在本地存储输入数据,页面重定向之前或在每个表单控件的焦点事件进行正确的:

饼干

好大的饼干可以来得心应手在这种情况下,但你应该考虑下方面:

  1. 即使你可以通过编程加密值; 因为我们将在客户端的合作,饼干是不是这个真正的安全。 Http-OnlySecure标记饼干不会帮助我们在这里,因为这些选项一起使用时cookie将被“送”来执行SSL(安全),不能从Javascript(仅HTTP)访问。
  2. 浏览器有一个cookie的大小限制。 从MSDN:“大多数浏览器支持高达4096个字节的cookie因为这个小小的限制,饼干最好用来存储少量数据”。 所以,如果你不看这个尺寸(当你写的cookie和/或通过限制通过控件的值maxlength属性); 这可能是一个问题。 (和修剪值是在这种情况下,最糟糕的事情)。
  3. 浏览器也有一个限度可以为每个站点设置cookie数目。 所以; 存储在所述饼干的形式数据时; 的设定为每个表单字段值饼干代替; 你应该将它们合并成一个或几块饼干; 为您的网站不超过这个限制。

尽管如此,光明的一面是,他们被所有浏览器都支持,如果你不通过cookie计划“缓存”敏感和过长的数据,那么你可以采用如下方案。 如果不是这种情况; 你应该更好地与下一个建议去: 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工作演示

注:“饼干读/写”从剧本developer.mozilla.org应该包含在上面的代码。 您还可以使用Yahoo的YUI 2:饼干实用 ,其有一个有用的setSub()用于设置子饼干一个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的对象,不同之处在于它存储的数据只有一个会话。

保存表单数据通过无声AJAX邮服务器/ DB(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的,当你测试浏览器支持设置。)
  • 否则,如果您有支持Storage对象; 去localStorage ;
  • ELSE IF [饼干当前会话存储] + [饼干大小表单数据需求] <4096个字节; 然后用cookies
  • 否则,如果你有一个服务器端的web应用程序使无声AJAX请求将数据存储在服务器上
  • ELSE不这样做。

注意:对于HTML5功能检测,看看这个页面或本页面 ,也可以使用Modernizr的 。

HTTPS问题

究其原因,使用HTTPS时,是所有形式的变化都消失了; 它是一个安全协议 。 形式大多用于用户输入,并且可以(可能)包含敏感数据。 所以这种行为似乎自然和预期。 我上面提供解决方案(S)将工作一样,他们对HTTP做。 所以这应该涵盖所有的顾虑。

延伸阅读:

  • 自动填充表单控件:autocomplete属性
  • HTML5的形式autocomplete属性
  • DOM存储
  • HTML5 Web存储
  • 对Web本地存储的未来
  • 饼干


文章来源: How to keep changed form content when leaving and going back to HTTPS page? (works with HTTP)