【问题标题】:How to make Chrome remember password for an AJAX form?如何让 Chrome 记住 AJAX 表单的密码?
【发布时间】:2011-07-22 18:07:46
【问题描述】:

我正在使用 AJAX 在我的登录页面上进行快速输入验证。如果一切正确,用户将被重定向。

代码如下:

$(form).submit(function () {
    $.post($(this).attr('action'), $(this).serialize(), function (data) {
        if (data.status == 'SUCCESS') {
            window.location = data.redirectUrl;
        }
   }
...

它在所有浏览器中都运行良好。但是Chrome有问题。它不提供保存密码。

当 JavaScript 关闭时,密码被保存,所以问题肯定是重定向到一个新的位置。

我该如何解决这个问题?

【问题讨论】:

  • 如果您使用的是e.preventDefault()return false,那么这是Chrome 中的一个错误:code.google.com/p/chromium/issues/detail?id=282488
  • 我在使用 Chrome 版本 50.0.2628.0 Canary 时遇到了同样的问题。奇怪的是,当我在本地主机上运行网站时,它建议保存密码。

标签: jquery ajax forms google-chrome passwords


【解决方案1】:

我为这个问题找到了一个肮脏的解决方法,通过插入一个不可见的 iframe 并将表单定位到它:

<iframe src="/blank.html" id="loginTarget" name="loginTarget" style="display:none">
</iframe>

<form id="loginForm" action="/blank.html" method="post" target="loginTarget"></form>

对应的JavaScript:

$('#loginForm').submit(function () {
    $.post('/login', $(this).serialize(), function (data) {
        if (data.status == 'SUCCESS') {
            window.location = data.redirectUrl;
        }
    })
})

诀窍是,确实有两个请求。首先表单被提交到 /blank.html,服务器会忽略它,但这会触发 Chrome 中的密码保存对话框。此外,我们发出 ajax 请求并将真实表单提交到 /login。由于第一个请求的目标是不可见的 iframe,因此页面不会刷新。

如果您不想重定向到另一个页面,这当然更有用。如果你想重定向,改变 action 属性是一个更好的解决方案。

编辑:

这是一个简单的JSFiddle 版本。与评论部分的声明相反,不需要重新加载页面,它似乎工作得非常可靠。我在带有 Chrome 的 Win XP 和带有 Chromium 的 Linux 上对其进行了测试。

【讨论】:

  • 重要的是要强调即使使用此解决方案,当前页面仍会重新加载。因此,尽管您没有重定向到另一个页面,但您正在重新加载当前页面。 Chrome 让 SPA 很难让 Chrome 记住用户的密码。相关问题:stackoverflow.com/questions/21191336/…
  • 此解决方案适用于我的应用程序。无需重新加载整个页面,只需更改 iframe 地址即可。我还必须让目标页面(blank.html,重命名为blank.php)返回一个随机字符串以使其工作。使用 method="post" 也是明智之举,这样明文密码就不会存储在服务器的访问日志中。
  • @hegemon 谢谢我添加了method="post",但您不必重新加载页面或iframe。只需删除“window.location = data.redirectUrl;”完全。我只是补充说,因为它是原始问题的一部分。在我的服务器上,blank.html 不存在,所以服务器返回 404 错误,但它仍然有效。
  • 不需要创建iframe,使用action="#"
  • 在 Chrome 版本 41.0.2272.104(64 位)上,提示 1Password,但 Chrome 没有
【解决方案2】:

您能否将表单的action 值更改为data.redirectUrl 并让表单像往常一样提交?这应该会触发浏览器提示保存用户名和密码。

$(form).submit(function () {
    $.post($(this).attr('action'), $(this).serialize(), function (data) {
        if (data.status == 'SUCCESS') {
            $("form#name").attr('action', data.redirectUrl);
        }
    }
...

【讨论】:

  • 这一行根本不会重定向。如果我添加 window.location = data.redirectUrl;之后,什么都没有改变。 Chrome 仍然拒绝保存密码...
  • @Alex:你可能在某个地方preventDefault()return falseing 吗?摆脱它,让表单做它通常做的事情。
  • 不,我不这样做。我猜这只是 Chrome 的错误,Web 开发人员无法修复它......
  • 你有没有试过这样做,然后做一个 $('form#name').trigger('submit');
  • Chrome 46 修复了它的错误行为 - 不再需要变通方法。见stackoverflow.com/a/33113374/810109
【解决方案3】:

在这里阅读 - why doesn't chrome recognize this login form?

重要的评论是:

是的,删除后它不起作用 返回假。你需要重写 你的代码。 Chrome 不提供 从不是的表单中保存密码 “提交”作为安全功能。如果 您希望保存密码功能 工作,你将不得不放弃 整个花哨的 AJAX 登录。

因此您可以考虑删除 Ajax 并让表单发布登录,这可能是没有启用 JavaScript 的用户也可以使用您的表单登录的唯一方法。

【讨论】:

  • 您可以放弃的另一件事是在 Chrome 中支持密码保存,并让用户对 Chrome 开发人员进行错误修复以修复浏览器。
  • Chrome 46 修复了它的错误行为——它现在可以工作了!见stackoverflow.com/a/33113374/810109
【解决方案4】:

我已经用这种方式修复了它:

<form action="/login"></form>

还有 JavaScript:

$(form).submit(function () {
   if(-1 !== this.action.indexOf('/login')) {
      var jForm = $(this);
      $.post(this.action, $(this).serialize(), function (data) {
         if (data.status == 'SUCCESS') {

            // change the form action to another url
            jForm[0].action = data.redirectUrl;

            // and resubmit -> so, no AJAX will be used 
            // and function will return true
            jForm.submit();
         }
      });
      return false;
   }
}

【讨论】:

    【解决方案5】:

    在我的情况下,Chrome 不记得密码,因为在一种形式中有两种不同的密码类型输入(以一种形式创建/登录)。在我的案例中,这个问题是通过使用 javascript 操作删除类型密码的输入之一来解决的,以便浏览器可以决定哪些提交的字段包含凭据数据。

    【讨论】:

      【解决方案6】:

      所以现在在 2019 年,我们可以使用 Credential Management API 来做到这一点。

      注意:这是实验性 API! 检查这个:https://developers.google.com/web/fundamentals/security/credential-management/save-forms

      基本代码:

      function onSubmit() {
          makeAjaxLoginRequest()
          .then((status) => {
              if (status.success) {
                  if (window.PasswordCredential) {
                      var cr = new PasswordCredential({ id: login, password: password });
                      return navigator.credentials.store(cr);
                  } else {
                      return Promise.resolve();
                  }
              }
          }).then(
              () => { // redirect || hide login window, etc... },
              () => { // show errors, etc... }
          )
      }
      

      【讨论】:

        【解决方案7】:

        我发现用户名和密码输入字段必须设置名称标签才能让 Chrome 提供保存密码。 This thread 是关于简单的表单,但同样修复了我的 jquery AJAX 表单提交。

        【讨论】:

          【解决方案8】:

          从昨天,2013 年 10 月 7 日,Chrome 28 开始,现在无需任何技巧即可实现。似乎他们解决了这个问题......

          【讨论】:

          • 确实,它看起来确实如此 - 尽管它似乎再次停止工作(Chrome 29)
          • 是的,这很奇怪,就像他们在 29 年再次禁用它一样
          • 精神错乱。 Chrome 需要支持这一点!
          • Chrome 46 修复了它的错误行为 - 不再需要变通方法。见stackoverflow.com/a/33113374/810109
          【解决方案9】:

          我遇到了同样的问题 - 如何强制浏览器存储 AJAX 请求的用户凭据。请在此处查看我的答案 - https://stackoverflow.com/a/64140352/994289

          希望对您有所帮助。至少它在 Windows 上的 Chrome 上运行良好。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-04-23
            • 2012-01-21
            • 2012-01-14
            • 1970-01-01
            • 1970-01-01
            • 2013-02-26
            • 1970-01-01
            • 2016-01-20
            相关资源
            最近更新 更多