离开和返回HTTPS页面时如何保持更改的表单内容?(适用于 HTTP) [英] How to keep changed form content when leaving and going back to HTTPS page? (works with HTTP)

查看:28
本文介绍了离开和返回HTTPS页面时如何保持更改的表单内容?(适用于 HTTP)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  1. 在文本区域中输入/更改内容
  2. 提交表单前,离开页面(例如点击浏览器的后退按钮)
  3. 返回编辑页面(例如点击前进按钮)

预期结果:textarea中输入的内容应该还在

Expected result: the content entered in the textarea should still be there

实际结果:

  • 使用HTTPS:所有更改都消失了(糟糕!)
  • 使用HTTP:变化仍然存在(好!)
  • with HTTPS: all changes are gone (bad!)
  • with HTTP: the changes are still there (good!)

为什么在使用 HTTPS 时会发生这种情况?我怎样才能防止这种情况?是浏览器还是网站负责?

Why is this happening when using HTTPS? How can I prevent this? Is the browser or the website responsible?

推荐答案

可以考虑以下解决方案:

You can consider the following solutions:

这似乎无关,因为 autocomplete 告诉浏览器使用值根据早期用户输入完成字段,这些值是随表单提交"的.但在我的测试中,我看到了这一点;填写表格后未提交;当我点击前进(历史)按钮并再次回击时;如果我设置了 autocomplete="on",表单字段会自动填充,当设置为 "off" 时,所有字段都会被清除.

This seems unrelated since autocomplete tells the browser to complete fields with the values based on earlier user input which were "submitted" with the form. But in my tests I saw that; after filling out the form without submitting; when I hit the forward (history) button and hit back again; form fields were auto-filled if I set autocomplete="on" and all were cleared when set to "off".

所以;(如果针对 HTML5 用户)您可以使用此属性来缓存"您的表单数据.(适用于所有主流浏览器,Opera 除外).

So; (if targeting HTML5 users) you can use this attribute to "cache" your form data. (Works on all major browsers, except 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> 

请注意,当表单控件的其余部分打开时,您可以为特定字段(在本例中为密码)设置自动完成功能.

Notice that you can set the auto-complete feature off for a specific field (password in this case) when the rest of the form controls are on.

MSDN 备注:

  • 如果缺少 autocomplete 属性,如果元素没有父表单,或者表单有自动完成设置为开启".
  • 自动完成功能提供的信息不会暴露给对象模型,并且在用户访问之前对网页不可见选择其中一项建议作为文本字段的值.

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

You can store the input data locally, right before the page redirection or on focus-out event of every form control:

在这种情况下,古老的 cookie 可以派上用场,但您应该考虑其缺点:

The good-old cookies can come handy in this case but you should consider the down-sides:

  1. 即使您可以以编程方式加密值;由于我们将在客户端工作,因此 cookie 并不是真正安全的.Http-OnlySecure 标记的 cookie 在这里对我们没有帮助,因为这些选项用于在 cookie 被发送"(安全)并且不能从Javascript(仅限 http).
  2. 浏览器有 cookie 大小限制.来自 MSDN:大多数浏览器都支持最多 4096 字节的 cookie.由于这个小限制,cookies最好用于存储少量数据". 所以,如果你不注意这个大小(当你写 cookie 和/或通过限制控件的值通过 maxlength 属性);那可能是一个问题.(在这种情况下,修剪值是最糟糕的事情).
  3. 浏览器对可以设置的 cookie 数量也有限制每个域.所以;将表单数据存储在 cookie 中时;而不是为每个表单字段值设置 cookie;您应该将它们合并为一个或几个 cookie;为您的网站不要超过此限制.
  1. Even though you can encrypt the values programmatically; since we will be working on the client-side, cookies are not truly secure for this. Http-Only and Secure marked cookies will not help us here, because these options are used to enforce SSL when the cookie is "sent" (secure) and cannot be accessed from Javascript (http-only).
  2. Browsers have a cookie size limit. From MSDN: "Most browsers support cookies of up to 4096 bytes. Because of this small limit, cookies are best used to store small amounts of data". So, if you don't watch for this size (when you write the cookie and/or by limiting the control's value via maxlength attributes); that could be a problem. (and trimming the value is the worst thing in this case).
  3. Browsers also have a limit to the number of cookies that can be set per domain. So; when storing the form data in the cookies; instead of setting cookies for each form field value; you should merge them into one or few cookies; for your site not to exceed this limit.

不过,好的一面是所有浏览器都支持它们,如果您不打算通过 Cookie 来缓存"敏感和过长的数据,那么您可以使用以下解决方案.如果不是这种情况;你最好采用下一个建议:localStorage.

Still, the bright side is they are supported by all browsers and if you don't plan to "cache" sensitive and too-long data via Cookies, then you can use the following solution. If this is not the case; you should better go with the next suggestion: 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 上的工作演示.

Here is a working demo on jsFiddle.

注意:developer.mozilla.org 应该包含在上面的代码中.您还可以使用 Yahoo 的 YUI 2: Cookie Utility,它有一个有用的 setSub() 用于在单个 cookie 中设置子 cookie 的方法,用于我之前提到的浏览器限制.

Note: The "cookies reader/writer" script from developer.mozilla.org should be included with the code above. You can also use Yahoo's YUI 2: Cookie Utility which has a useful setSub() method for setting sub-cookies inside a single cookie, for the browser limit that I previously mentioned.

您还可以使用更现代的技术,例如 localStorage (HTML5).它更安全、更快.所有主流浏览器都支持此功能,包括 IE 8+.(此外,还支持 iOS 和 Android!)

You can also use more modern techniques like localStorage (HTML5). It is more secure and faster. All major browsers support this feature including IE 8+. (Additionally, iOS and Android support!)

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
}

所以,就像在 cookie 示例中一样;

So, just like in the cookies example;

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

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

会话存储

这几乎以相同的方式工作.来自 W3C:sessionStorage 对象等同于 localStorage 对象,只是它只存储一个会话的数据.

SessionStorage

This works pretty much the same way. From W3C: The sessionStorage object is equal to the localStorage object, except that it stores the data for only one session.

不是一种非常有效的方法,但您可能希望在其他方法不可行的情况下使用它.您可以在 beforeunload 事件上发布帖子并向用户提示消息.

Not a very efficient way but you might want to use this where others are not feasible. You can make the post on the beforeunload event and prompt a message to the user.

$(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...";
});

在页面加载时从服务器检索以前保存的数据:

只是提醒你;例如,如果用户正在填写更新"表单;您可以随时从服务器获取之前保存的数据并自动填写表单(非敏感字段).

Retrieve Previously Saved Data from Server on Page Load:

Just to remind you; if the user is filling out an "update" form, for example; you can always fetch the previously saved data from the server and automatically fill in the form (non-sensitive fields).

如果你真的需要这个并且值得麻烦;您应该考虑实现回退机制的跨浏览器解决方案;例如:

If you really need this and worth the trouble; you should consider a cross-browser solution that implements a fall-back mechanism; such as:

  • 如果您支持 HTML5 功能;使用 HTML5 自动完成属性.(您可以预先在 HTML 中嵌入该属性,或者在测试浏览器支持时通过 Javascript/jQuery 设置它.)
  • ELSE 如果您支持 Storage 对象;一起去localStorage;
  • ELSE IF [cookies 您当前的会话存储] + [cookie 大小您的表单数据需求] <4096 字节;然后使用 cookies.
  • ELSE 如果您有一个服务器端 Web 应用程序向在服务器上存储数据.
  • 否则不要这样做.

注意:对于 HTML5 功能检测,请查看此页面此页面 或者您可以使用Modernizr.

Note: For HTML5 feature detection, take a look at this page or this page or you can use Modernizr.

HTTPS 问题:

使用HTTPS时所有表单更改都消失的原因是;它是一个安全协议.表单主要用于用户输入并且可以(可能)包含敏感数据.所以这种行为似乎是自然而然的.我上面提供的解决方案的工作方式与它们在 HTTP 上的工作方式相同.所以这应该涵盖您所有的担忧.

The reason, all form changes are gone when using HTTPS is that; it is a secure protocol. Forms are mostly used for user input and can (probably) contain sensitive data. So this behavior seems natural and expected. The solution(s) I offer above will work the same as they do on HTTP. So that should cover all your concerns.

这篇关于离开和返回HTTPS页面时如何保持更改的表单内容?(适用于 HTTP)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆