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

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

问题描述


  • 在textarea中输入/更改内容

  • 在提交表单之前,请离开页面(例如,通过点击浏览器的后退按钮)

  • 返回到编辑页面(例如通过点击转发按钮)

  • 预期结果:输入的内容textarea仍然存在



    实际结果:使用 HTTPS


    • :所有更改均已消失(坏!)
    • 使用 HTTP
    • :更改仍然存在好!)



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

    解决方案

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

    autocomplete 属性(HTML5)



    autocomplete 会告诉浏览器完成使用表单提交的基于早期用户输入的值的字段。但在我的测试中,我看到了这一点;填写表格后未提交;当我击中前进(历史)按钮并再次回击时;如果我将 autocomplete =on设置为off时清除了所有表单字段, 。

    那么; (如果定位HTML5用户),则可以使用此属性缓存表单数据。 (适用于除Opera之外的所有主流浏览器)。


    $ b

     < form action =/ update method =postautocomplete =on> 
    电子邮件地址:< input type =textid =email/>< br />
    用户名:< input type =textid =uname/>< br />
    密码:< input type =passwordid =pwdautocomplete =off/>< br />
    < input type =submit/>
    < / form>

    请注意,您可以为特定字段设置自动完成功能(在这种情况下为密码)当其他窗体控件打开时。



    MSDN备注:


    • 如果缺少autocomplete属性,那么如果元素没有父表单,或者表单中有
      ,则字段将默认为'on'状态autocomplete设置为'on'。

    • 由AutoComplete功能提供的信息不会暴露给
      对象模型,并且对Web不可见直到用户
      选择其中一个建议作为文本字段的值。
    • 在本地未提交表单数据:

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



      Cookie



      这种情况下,考虑到以下方面:即使您可以通过编程方式加密这些值,由于我们将在客户端进行工作,因此Cookie并不真正安全。 仅限Http 安全标记的Cookie不会帮助我们,因为这些选项用于在cookie是已发送(安全),并且无法通过Javascript(仅限http)访问。

    • 浏览器具有Cookie大小限制。来自 MSDN 大多数浏览器支持高达4096字节的
      cookies。由于这个小限制,cookies
      最适合用于存储少量数据。
      因此,如果您没有
      注意这个大小(当您编写cookie和/或通过限制
      控制的值通过 maxlength 属性);这可能是一个
      问题。 (在这种情况下修剪该值是最糟糕的事情)。
    • 浏览器对每个域可设置
      的cookie数量也有限制。所以;当将表单数据存储在cookie中时;而不是为每个表单字段值设置Cookie;你应该将它们合并成一个或几个cookie;为您的网站不超过
      超过此限制。

    • 不过,光明的一面是它们受到所有浏览器的支持,您不打算通过Cookie缓存敏感和过长的数据,那么您可以使用以下解决方案。如果情况并非如此;你应该更好地使用下面的建议: localStorage

        //下面只是一个演示,并没有通过任何方式对
      //生产就绪Web应用程序进行彻底测试。
      //但它应该给你一个想法。

      / **
      *从目标表单缓存用户输入数据,将其存储在cookie
      *中,并在需要或需要时将其提交回表单。
      * /
      var formCache =(function(){
      var _form = null,
      _formData = [],
      _strFormElements =input [type ='text' ],
      +input [type ='checkbox'],
      +input [type ='radio'],
      // +input [type ='password' ],//输入密码字段
      +input [type ='hidden'],
      // +input [type ='image'],
      +input [type ='file'],
      //更多输入类型...
      +input [type ='email'],
      +input [type ='tel' ],
      +input [type ='url'],
      +select,
      +textarea;

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

      return {
      $ b $ / **
      *初始化带目标表单(id)的formCache。
      *您可以传递formId参数的任何容器ID,formCache将
      *仍然在给定容器内查找表单元素。如果没有表单id
      *被传递,它会将第一个< form>元素在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);
      返回formCache; //使其可链接
      },

      / **
      *将表单数据存储在cookie中。
      * /
      save:function(){
      if(_form === null)return _warn();
      $ b _form
      .find(_strFormElements)
      .each(function(){
      var f = $(this).attr('id')+': '+ formCache.getFieldValue($(this));
      _formData.push(f);
      });
      docCookies.setItem('formData',_formData.join(),31536e3); // 1年到期(持久)
      console.log('缓存表单数据:',_formData);
      返回formCache;
      },

      / **
      *填写以前存储在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]);
      });
      返回formCache;
      },

      / **
      *从以前存储的数据中设置指定表单域的值。
      * /
      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);
      }
      返回formCache;
      },

      / **
      *获取指定表单域的以前存储的值。
      * /
      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 else null;
      },

      / **
      *清除缓存并从cookie中删除先前存储的表单数据。
      * /
      clear:function(){
      _formData = [];
      docCookies.removeItem('formData');
      返回formCache;
      },

      / **
      *清除所有表单域。
      *这与form.reset()不同,它只将字段
      *重新设置为它们的初始值。
      * /
      clearForm:function(){
      _form
      .find(_strFormElements)
      .each(function(){
      var elem = $(这个);
      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);
      }
      });
      返回formCache;
      }
      };
      })();
      $ b $ // //在我们卸载表单页面之前保存表单数据
      $(window).on('beforeunload',function(event){
      formCache.save() ;
      返回false;
      });

      //当我们加载表单页面时,初始化和获取表单数据(如果存在)
      $(document).on('ready',function(event){
      formCache.init()。fetch();
      });

      这是 在jsFiddle上的演示


      $ b 注意: developer.mozilla.org 应包含在上面的代码中。您还可以使用雅虎的 YUI 2:Cookie实用程序,它有一个有用的 setSub()方法,用于在单个Cookie内设置子Cookie,以用于前面提到的浏览器限制。



      localStorage



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


      $ b

        if(typeof Storage!=='undefined' ){//我们有本地存储支持
      localStorage.username ='Onur'; //保存到本地存储
      document.getElementById('uname')。value = localStorage.username; //从本地存储中获取
      }

      所以,就像在cookies示例中那样;
      $ b

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

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



      SessionStorage



      <这种工作方式几乎相同。来自W3C:sessionStorage对象与localStorage对象相同,只不过它仅存储一个会话的数据。



      通过无声AJAX发布将表单数据保存到服务器/数据库(s):



      不是一种非常有效的方式,但您可能想在别人不可行的情况下使用它。您可以在事件之前在事件上发帖,并向用户提示一条消息。
      $ b

        $(window).on('beforeunload',function(event){
      //检查是否至少填写了一个字段
      //如果填写了AJAX帖子
      返回您没有提交表单就离开页面......;
      });



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



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

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


      • 如果您支持HTML5功能,使用 HTML5 自动完成
        属性
        。 (您可以事先在HTML中嵌入属性,或者当您测试浏览器支持时,
        通过Javascript / jQuery设置它。)

      • 否则如果您支持存储对象;请使用
        localStorage ;

      • 否则如果[当前会话存储Cookie] + [ cookie大小
        表格数据需求]< 4096字节;然后使用 cookies
      • 否则如果您有服务器端网络应用程序,请将沉默的AJAX请求到
        在服务器上存储数据

      • 否则不需要。



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



      HTTPS问题

      原因是,使用 HTTPS 时,所有表单更改都消失了;它是 安全协议 。表单主要用于用户输入,可能(可能)包含敏感数据。所以这种行为看起来很自然和预期。我上面提供的解决方案将与HTTP中的解决方案相同。所以这应该涵盖你所有的顾虑。

      进一步阅读:




      1. Enter/change something in a textarea
      2. Before submitting the form, leave the page (e.g. by clicking browser's back button)
      3. Go back to the edit page (e.g. by clicking the forward button)

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

      Actual result:

      • with HTTPS: all changes are gone (bad!)
      • with HTTP: the changes are still there (good!)

      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:

      The autocomplete Attribute (HTML5)

      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".

      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 Remarks:

      • If the autocomplete attribute is missing, the field will default to an 'on' state if element has no parent form, or if the form has autocomplete set to 'on'.
      • Information provided by the AutoComplete feature is not exposed to the object model, and is not visible to a Web page until the user selects one of the suggestions as a value for the text field.

      Save the Un-submitted Form Data Locally:

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

      Cookies

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

      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.

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

      Here is a working demo on jsFiddle.

      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

      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
      }
      

      So, just like in the cookies example;

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

      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.

      Save Form Data to Server/DB via Silent AJAX Post(s):

      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).

      Conclusion

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

      • IF you have support for HTML5 features; use HTML5 autocomplete attribute. (You can embed the attribute in the HTML beforehand, or set it via Javascript/jQuery when you test for browser support.)
      • ELSE IF you have support for the Storage object; go with localStorage;
      • ELSE IF [cookies your current session stores] + [cookie size your form data needs] < 4096 bytes; then use cookies.
      • ELSE IF you have a server-side web-app make silent AJAX requests to store data on server.
      • ELSE don't do it.

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

      HTTPS Problem:

      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.

      Further reading:

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

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