ChatGPT解决这个技术问题 Extra ChatGPT

如何让浏览器提示保存密码?

嘿,我正在开发一个具有如下登录对话框的 Web 应用程序:

用户单击“登录”登录表单 HTML 使用 AJAX 加载并显示在页面上的 DIV 用户输入用户/密码字段并单击提交。这不是

-- 用户/密码是通过 AJAX 提交的再试一次。

这就是问题所在:浏览器从不提供通常的“保存此密码?是/从不/现在不”提示,它对其他网站提供。

我尝试使用“autocomplete='on'”将 <div> 包装在 <form> 标记中,但这没有任何区别。

是否可以让浏览器提供存储密码而无需对我的登录流程进行重大修改?

谢谢埃里克

ps补充一下我的问题,我肯定在使用存储密码的浏览器,而且我从来没有点击过“从不使用这个网站”......这是一个技术问题,浏览器没有检测到它是一个登录表单,而不是操作员错误:-)

不要忘记并非所有浏览器都可以存储密码。
可能是浏览器提供了保存您的用户/通行证,然后您单击了“不再询问!” ?

d
dragonfire

我找到了这个问题的完整解决方案。 (我已经在 Chrome 27 和 Firefox 21 中对此进行了测试)。

有两件事要知道:

触发“保存密码”,并恢复保存的用户名/密码

1.触发“保存密码”:

对于 Firefox 21,当检测到有一个包含输入文本字段的表单并提交了输入密码字段时,会触发“保存密码”。所以我们只需要使用

$('#loginButton').click(someFunctionForLogin);
$('#loginForm').submit(function(event){event.preventDefault();});

someFunctionForLogin() 执行 ajax 登录并重新加载/重定向到登录页面,而 event.preventDefault() 由于提交表单而阻止原始重定向。

如果你只使用 Firefox,上面的解决方案就足够了,但它在 Chrome 27 中不起作用。然后你会问如何在 Chrome 27 中触发“保存密码”。

对于 Chrome 27,通过提交包含属性 name='username' 的输入文本字段和属性 name='password' 的输入密码字段的表单将其重定向到页面后会触发“保存密码”。因此,我们不能因为提交表单而阻止重定向,但我们可以在完成 ajax 登录后进行重定向。 (如果您希望ajax登录不重新加载页面或不重定向到页面,不幸的是,我的解决方案不起作用。)然后,我们可以使用

<form id='loginForm' action='signedIn.xxx' method='post'>
    <input type='text' name='username'>
    <input type='password' name='password'>
    <button id='loginButton' type='button'>Login</button>
</form>
<script>
    $('#loginButton').click(someFunctionForLogin);
    function someFunctionForLogin(){
        if(/*ajax login success*/) {
            $('#loginForm').submit();
        }
        else {
            //do something to show login fail(e.g. display fail messages)
        }
    }
</script>

type='button' 的按钮将使单击按钮时不提交表单。然后,将函数绑定到 ajax 登录按钮。最后,调用 $('#loginForm').submit(); 会重定向到登录页面。如果登录页面是当前页面,则可以将“signedIn.xxx”替换为当前页面以进行“刷新”。

现在,你会发现 Chrome 27 的方法也适用于 Firefox 21。所以最好还是使用它。

2.恢复保存的用户名/密码:

如果您已经将 loginForm 硬编码为 HTML,那么您将发现在 loginForm 中恢复保存的密码没有问题。但是,如果您使用 js/jquery 动态制作 loginForm,则保存的用户名/密码不会绑定到 loginForm,因为保存的用户名/密码仅在文档加载时绑定。因此,您需要将 loginForm 硬编码为 HTML,并使用 js/jquery 动态移动/显示/隐藏 loginForm。

备注:如果你是ajax登录,不要在标签形式中添加autocomplete='off',如

<form id='loginForm' action='signedIn.xxx' autocomplete='off'>

autocomplete='off' 会使将用户名/密码还原到 loginForm 失败,因为您不允许它“自动完成”用户名/密码。


在 Chrome 中,“event.preventDefault()”会阻止显示“保存密码”提示,请参阅此错误:code.google.com/p/chromium/issues/detail?id=282488
对于其他偶然发现此问题的人,我认为他们正在为此发布修复程序:code.google.com/p/chromium/issues/detail?id=357696
很多用户使用 ENTER 键提交表单,因为您在用户提交表单时有 prevented default,所以什么都不会发生,这是糟糕的用户体验。您可以在提交时检查回车键 keycode,但是您将再次进入乞求...
Chrome 46 修复了它的错误行为 - 不再需要变通方法。请参阅stackoverflow.com/a/33113374/810109
工作不可靠,如果您从 Javascript 提交,某些浏览器不会触发“记住”功能。
d
dragonfire

使用按钮登录:

如果您使用带有 onclick 处理程序的 type="button" 来使用 ajax 登录,那么 浏览器将不会提供来保存密码。

<form id="loginform">
 <input name="username" type="text" />
 <input name="password" type="password" />
 <input name="doLogin"  type="button" value="Login" onclick="login(this.form);" />
</form>

由于此表单没有提交按钮并且没有操作字段,因此浏览器不会提供保存密码的功能。

使用提交按钮登录:

但是,如果您将按钮更改为 type="submit" 并处理提交,则浏览器将提供保存密码。

<form id="loginform" action="login.php" onSubmit="return login(this);">
 <input name="username" type="text" />
 <input name="password" type="password" />
 <input name="doLogin"  type="submit" value="Login" />
</form>

使用这种方法,浏览器应该提供保存密码。

这是两种方法中使用的 Javascript:

function login(f){
    var username = f.username.value;
    var password = f.password.value;

    /* Make your validation and ajax magic here. */

    return false; //or the form will post your data to login.php
}

@Bigood因为它有效,而接受的答案却没有(至少对我而言)。谢谢斯派森!
在 IE 中也适用于我。我现在可以吻你了!
也为我工作.. :)
这是正确的,也是解决问题的最优雅的方法。
它之所以有效,是因为我只需复制第二个代码并通过检查元素将其粘贴到登录页面,在该页面上新添加的字段中输入用户名/密码,然后按登录,然后它会提示我保存用户/密码。然后我刷新页面瞧,它提示我选择已经保存的用户/通行证;)
T
TK421

我自己一直在努力解决这个问题,我终于能够找到问题以及导致它失败的原因。

这一切都源于我的登录表单被动态注入页面(使用backbone.js)。一旦我将登录表单直接嵌入到我的 index.html 文件中,一切都像魅力一样。

我认为这是因为浏览器必须知道存在一个现有的登录表单,但是由于我的表单是动态注入到页面中的,它不知道曾经存在过“真实的”登录表单。


从 Chrome 版本 46 开始,您现在还可以动态注入表单,它们将被识别为可以保存凭据的“真实”登录表单。请参阅stackoverflow.com/a/33113374/810109
B
Bert F

这个解决方案对我有用,由 Eric 在codingforums 上发布

之所以不提示,是因为浏览器需要页面物理刷新回服务器。您可以做的一个小技巧是对表单执行两个操作。第一个动作是 onsubmit 让它调用你的 Ajax 代码。还让表单以隐藏的 iframe 为目标。

代码:

<iframe src="ablankpage.htm" id="temp" name="temp" style="display:none"></iframe>
<form target="temp" onsubmit="yourAjaxCall();">

看看这是否会导致出现提示。

埃里克

发布于 http://www.codingforums.com/showthread.php?t=123007


作为说明,我发现如果表单为 submitted to itself,Chrome 11 不会提供保存您的凭据。因此,您需要将 action 设置为某个虚拟页面。
这将在 url 中发送密码明文作为获取请求。如果方法更改为 POST,Firefox (16) 将在新选项卡中打开以前隐藏的框架。 android 4 上的 chrome 也是如此。:-(
Chrome 46 修复了它的错误行为 - 不再需要 iframe 变通方法。请参阅stackoverflow.com/a/33113374/810109
M
Michal Roharik

有一个终极解决方案可以强制所有浏览器(已测试:chrome 25、safari 5.1、IE10、Firefox 16)使用 jQuery 和 ajax 请求请求保存密码:

JS:

$(document).ready(function() {
    $('form').bind('submit', $('form'), function(event) {
        var form = this;

        event.preventDefault();
        event.stopPropagation();

        if (form.submitted) {
            return;
        }

        form.submitted = true;

        $.ajax({
            url: '/login/api/jsonrpc/',
            data: {
                username: $('input[name=username]').val(),
                password: $('input[name=password]').val()
            },
            success: function(response) {
                form.submitted = false;
                form.submit(); //invoke the save password in browser
            }
        });
    });
});

HTML:

<form id="loginform" action="login.php" autocomplete="on">
    <label for="username">Username</label>
    <input name="username" type="text" value="" autocomplete="on" />
    <label for="password">Password</label>
    <input name="password" type="password" value="" autocomplete="on" />
   <input type="submit" name="doLogin" value="Login" />
</form>

诀窍是停止表单以自己的方式提交 (event.stopPropagation()),而是发送您自己的代码 ($.ajax()),然后在 ajax 的成功回调中再次提交表单,以便浏览器捕获并显示要求保存密码。您还可以添加一些错误处理程序等。

希望它对某人有所帮助。


这实际上会对 login.php?username=username&password=password 进行 HTTP 访问,这首先取消了保存密码的全部目的
呜呜呜呜呜呜呜呜呜呜呜!这对我有用;)非常感谢!
是的,将 event listener 添加到表单中并添加 event.preventDefault()event.stopPropagation()
D
Danny Wave

简单的 2020 方法

这将自动启用自动完成并在浏览器中保存密码。

自动完成=“开”(表格)

自动完成=“用户名”(输入,电子邮件/用户名)

autocomplete="current-password" (输入,密码)

<form autocomplete="on">
  <input id="user-text-field" type="email" autocomplete="username"/>
  <input id="password-text-field" type="password" autocomplete="current-password"/>
</form>

在 Apple 的文档中查看更多信息:Enabling Password AutoFill on an HTML Input Element


仅供参考,这似乎需要提交表单(不能使用 XHR 和 preventDefault),如果只有一个密码字段(数字安全类型的应用程序),它将不起作用。将这些发现分享给其他可能觉得有用的人。
C
Community

我尝试了 spetson's answer,但这对我在 Chrome 18 上不起作用。起作用的是将负载处理程序添加到 iframe 并且不中断提交(jQuery 1.7):

function getSessions() {
    $.getJSON("sessions", function (data, textStatus) {
        // Do stuff
    }).error(function () { $('#loginForm').fadeIn(); });
}
$('form', '#loginForm').submit(function (e) {
    $('#loginForm').fadeOut();
}); 
$('#loginframe').on('load', getSessions);
getSessions();

的HTML:

<div id="loginForm">
    <h3>Please log in</h3>
    <form action="/login" method="post" target="loginframe">
            <label>Username :</label>
            <input type="text" name="login" id="username" />
            <label>Password :</label>
            <input type="password" name="password" id="password"/>
            <br/>
            <button type="submit" id="loginB" name="loginB">Login!</button>
    </form>
</div>
<iframe id="loginframe" name="loginframe"></iframe>

getSessions() 执行 AJAX 调用并在失败时显示 loginForm div。 (如果用户未通过身份验证,Web 服务将返回 403)。

经过测试也可以在 FF 和 IE8 中工作。


我在 Chrome 中尝试了这种方法,除非操作页面(您的示例中的 /login)返回一些文本或其他可见内容,否则它不会起作用。
Chrome 46 修复了它的错误行为 - 不再需要 iframe 变通方法。请参阅stackoverflow.com/a/33113374/810109
C
Community

浏览器可能无法检测到您的表单是登录表单。根据 this previous question 中的一些讨论,浏览器会查找类似于 <input type="password"> 的表单字段。您的密码表单字段是否与此类似?

编辑:为了回答您的问题,我认为 Firefox 通过 form.elements[n].type == "password" 检测密码(遍历所有表单元素),然后通过在表单元素中向后搜索文本字段之前的文本字段来检测用户名字段密码字段(更多信息 here)。据我所知,您的登录表单必须是 <form> 的一部分,否则 Firefox 不会检测到它。


它是相似的,是的,谢谢,我会接受这个作为官方答案,因为这与我们得到的差不多。令人沮丧的是:我似乎无法(在网络上的任何地方)找到一篇简单的博客文章,上面写着“这是浏览器用来检测您填写的表单是否是登录表单的规则,因此他们可以提供保存用户的密码。”考虑到这有点黑魔法(并且至少考虑到 Mozilla 是开源的),你会认为有人会发布启发式方法。
(同样,我似乎没有办法“提示”我的登录表单,以便浏览器知道它是一个登录表单。再一次,令人惊讶的是,这在网络上并没有得到更好的记录。我认为我的更改将是表单字段名称和整体 HTML 结构,然后我希望 [!] 可以解决问题。)
好吧,没有运气。我从稍微不同的角度提出了一个新问题:stackoverflow.com/questions/2398763/…
S
Simon Backx

没有一个答案表明您可以使用 HTML5 History API 提示保存密码。

首先,您需要确保至少有一个带有密码和电子邮件或用户名字段的 <form> 元素。只要您使用正确的输入类型(密码、电子邮件或用户名),大多数浏览器都会自动处理此问题。但可以肯定的是,为每个输入元素正确设置自动完成值。

您可以在此处找到自动完成值的列表:https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete

您需要的是:usernameemailcurrent-password

那么你有两种可能:

如果您在提交后导航到不同的 URL,大多数浏览器会提示保存密码。

如果您不想重定向到不同的 URL 或什至重新加载页面(例如单页应用程序)。只需在表单的提交处理程序中阻止事件默认值(使用 e.preventDefault)。您可以使用 HTML5 历史 API 在历史上推送某些内容,以指示您在单页应用程序中“导航”。浏览器现在将提示保存密码和用户名。

history.pushState({}, "Your new page title");

您还可以更改页面的 URL,但这不是提示保存密码所必需的:

history.pushState({}, "Your new page title", "new-url");

文档:https://developer.mozilla.org/en-US/docs/Web/API/History/pushState

这还有一个额外的好处,即如果用户输入的密码不正确,您可以防止浏览器要求保存密码。请注意,在某些浏览器中,即使您调用 .preventDefault 并且不使用历史 API,浏览器也会始终要求保存凭据。

如果您不想离开和/或修改浏览器历史记录,您可以使用 replaceState 代替(这也有效)。


这是2020年的答案!我必须使用 history.pushState({}, null "Your new page title"); 来更改网址,而无需任何导航
c
captainclam

我花了很多时间阅读这个线程上的各种答案,对我来说,它实际上略有不同(相关,但不同)。在 Mobile Safari(iOS 设备)上,如果页面加载时登录表单为 HIDDEN,则不会出现提示(显示表单后提交)。您可以使用以下代码进行测试,该代码会在页面加载后 5 秒显示表单。删除 JS 和 display: none 并且它可以工作。我还没有找到解决方案,只是发布以防其他人有同样的问题并且无法找出原因。

JS:

$(function() {
  setTimeout(function() {
    $('form').fadeIn();
  }, 5000);
});

HTML:

<form method="POST" style="display: none;">
  <input name='email' id='email' type='email' placeholder='email' />
  <input name='password' id='password' type='password' placeholder='password' />
  <button type="submit">LOGIN</button>
</form>

D
David Rettenbacher

以下代码经过测试

铬 39.0.2171.99m:工作

Android Chrome 39.0.2171.93:工作

Android股票浏览器(Android 4.4):不工作

Internet Explorer 5+(模拟):工作

Internet Explorer 11.0.9600.17498 / 更新版本:11.0.15:工作

Firefox 35.0:工作

JS-小提琴:
http://jsfiddle.net/ocozggqu/

邮政编码:

// modified post-code from https://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit
function post(path, params, method)
{
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.

    var form = document.createElement("form");
    form.id = "dynamicform" + Math.random();
    form.setAttribute("method", method);
    form.setAttribute("action", path);
    form.setAttribute("style", "display: none");
    // Internet Explorer needs this
    form.setAttribute("onsubmit", "window.external.AutoCompleteSaveForm(document.getElementById('" + form.id + "'))");

    for (var key in params)
    {
        if (params.hasOwnProperty(key))
        {
            var hiddenField = document.createElement("input");
            // Internet Explorer needs a "password"-field to show the store-password-dialog
            hiddenField.setAttribute("type", key == "password" ? "password" : "text");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }
    }

    var submitButton = document.createElement("input");
    submitButton.setAttribute("type", "submit");

    form.appendChild(submitButton);

    document.body.appendChild(form);

    //form.submit(); does not work on Internet Explorer
    submitButton.click(); // "click" on submit-button needed for Internet Explorer
}

评论

对于动态登录表单,需要调用 window.external.AutoCompleteSaveForm

Internet Explorer 需要一个“密码”字段来显示存储密码对话框

Internet Explorer 似乎需要点击提交按钮(即使是虚假点击)

这是一个示例 ajax 登录代码:

function login(username, password, remember, redirectUrl)
{
    // "account/login" sets a cookie if successful
    return $.postJSON("account/login", {
        username: username,
        password: password,
        remember: remember,
        returnUrl: redirectUrl
    })
    .done(function ()
    {
        // login succeeded, issue a manual page-redirect to show the store-password-dialog
        post(
            redirectUrl,
            {
                username: username,
                password: password,
                remember: remember,
                returnUrl: redirectUrl
            },
            "post");
    })
    .fail(function ()
    {
        // show error
    });
};

评论

如果成功,“帐户/登录”设置一个 cookie

页面重定向(“手动”由 js 代码启动)似乎是必需的。我还测试了一个 iframe-post,但我没有成功。


m
mwieczorek

我为 Prototype.JS 用户找到了一个相当优雅的解决方案(或 hack,任何合适的),它是使用 Prototype 的最后一个坚持者之一。相应的 jQuery 方法的简单替换应该可以解决问题。

首先,确保有一个 <form> 标记,以及一个嵌套在样式设置为 display:none 的元素中的类名称(在本例中为 faux-submit)的提交按钮,如下图所示:

<form id="login_form" action="somewhere.php" method="post">
    <input type="text" name="login" />
    <input type="password" name="password" />
    <div style="display:none">
        <input class="faux-submit" type="submit" value="Submit" />
    </div>
    <button id="submit_button">Login</button>
</form>

然后为 button 创建一个点击观察者,它将“提交”表单,如图所示:

$('submit_button').observe('click', function(event) {
    $('login_form').submit();
});

然后为 submit 事件创建一个侦听器并停止它。 event.stop() 将停止 DOM 中的所有提交事件,除非它包含在具有隐藏输入按钮类的 Event.findElement 中(如上,faux-submit):

document.observe('submit', function(event) {
    if (event.findElement(".faux-submit")) { 
        event.stop();
    }
});

这在 Firefox 43 和 Chrome 50 中经过测试。


D
Dave.Sol

您的站点可能已经在通知浏览器不要提示保存密码的列表中。在 Firefox 中,选项 -> 安全 -> 记住站点密码[复选框] - 例外[按钮]


m
maxisam

在@Michal Roharik 的回答中添加更多信息。

如果您的 ajax 调用将返回一个返回 url,您应该在调用 form.submit 之前使用 jquery 将表单操作属性更改为该 url

前任。

$(form).attr('action', ReturnPath);
form.submitted = false;
form.submit(); 

I
Igor

我有类似的问题,登录是使用 ajax 完成的,但是如果使用 ajax 提交表单(#loginForm),浏览器(firefox、chrome、safari 和 IE 7-10)将不会提供保存密码。

作为解决方案,我已将隐藏提交输入 (#loginFormHiddenSubmit) 添加到由 ajax 提交的表单中,并且在 ajax 调用返回成功后,我将触发单击隐藏提交输入。页面需要以任何方式刷新。点击可以通过以下方式触发:

jQuery('#loginFormHiddenSubmit').click();

我添加隐藏提交按钮的原因是:

jQuery('#loginForm').submit();

不会提供在 IE 中保存密码(尽管它已在其他浏览器中工作)。


T
Tài Hatranduc

我已经尝试了所有方法。没有什么是完全有效的。这是我的解决方案。这个对我有用。我希望它对你有用。我用文本区域替换电子邮件/用户名输入

<form>
<textarea required placeholder="Email" rows=1></textarea>
<input required placeholder="Password" type="password" readonly onfocus="this.removeAttribute('readonly')" />
<button>
    Sign in
</button>

B
Buhake Sindi

并非每个浏览器(例如 IE 6)都有记住凭据的选项。

您可以做的一件事是(一旦用户成功登录)通过 cookie 存储用户信息并具有“在这台机器上记住我”选项。这样,当用户再次访问时(即使他已注销),您的 Web 应用程序可以检索 cookie 并获取用户信息(用户 ID + 会话 ID)并允许他/她继续工作。

希望这可以是暗示性的。 :-)


我不会将用户信息存储在 cookie 中,至少不会存储任何敏感信息。
我不是说要存储用户密码。显然,您必须非常有创意地创建 useful garbage 来识别用户信息。甚至 SO 也将信息存储在 cookie 中以识别您。
很公平,但我仍然会尽可能多地加密。
@JackMarchetti 对其客户端进行加密将是一个糟糕(而且有点无用)的想法。由于加密所需的代码是可见的,因此任何人都可以找到 .js 文件并对其进行解密。这意味着您不应将数据存储在 cookie 中
J
Jack Marchetti

事实是,您不能强迫浏览器询问。我确信浏览器有它自己的算法来猜测您是否输入了用户名/密码,例如寻找 type="password" 的输入,但您不能设置任何东西来强制浏览器。

正如其他人建议的那样,您可以在 cookie 中添加用户信息。如果你这样做,你最好至少加密它并且不要存储他们的密码。也许最多存储他们的用户名。


我说要加密您存储在其中的任何内容。
饼干?这是一个等待发生的坏主意
h
harriyott

您可以将对话框附加到表单,因此所有这些输入都在表单中。另一件事是在用户名文本字段之后制作密码文本字段。


S
ShelatoBaboon

这对我来说效果更好,因为它是 100% ajaxed 并且浏览器检测到登录。

<form id="loginform" action="javascript:login(this);" >
 <label for="username">Username</label>
 <input name="username" type="text" value="" required="required" />
 <label for="password">Password</label>
 <input name="password" type="password" value="" required="required" />
 <a href="#" onclick="document.getElementById("loginform").submit();"  >Login</a>
</form>

M
Mandrig

使用 cookie 可能是最好的方法。

你可以有一个复选框“还记得我吗?”并让表单创建一个cookie来存储//用户的登录信息//信息。编辑:用户会话信息

要创建 cookie,您需要使用 PHP 处理登录表单。