注意:此问题已在其原始版本中进行了大量编辑。这个问题已经大大简化了。
之前已经多次提出类似的问题,不同的形式 - 例如,
How can I get browser to prompt to save password?
How does browser know when to prompt user to save password?
然而,这个问题涉及到Chrome功能的一个非常具体的方面,所以在这方面它是完全不同的。
根据过去的答案判断,让Chrome提示输入密码的最佳方法是将表单提交给虚拟iframe,同时实际通过AJAX登录:{{3} }。这对我来说很有意义,所以我现在已经花了几天的时间来摆弄一些示例代码。但是,Chrome在这方面的行为对我来说没有意义。完全没有。因此问题。
出于某种原因,如果在 onDomReady 之后/之后存在提交到虚拟iframe的表单,则Chrome不会提示您保存密码。
可以找到一个jsfiddle example,但它没什么用处,因为你必须在本地创建dummy.html
才能看到所描述的行为。因此,查看此内容的最佳方法是将完整的html复制到您自己的index.html
中,然后再创建一个dummy.html
文件。
以下是index.html
的完整代码。这三种方法突出显示为(1)
,(2)
,(3)
。只有(2)
才能确保提示用户保存自己的密码,(3)
不起作用的事实对我来说特别困惑。
<html>
<head>
<title>Chrome: Remember Password</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript">
$(function(){
function create_login_form()
{
$('#login_form').html(
"<input type='text' name='email'>" +
"<input type='password' name='password'>" +
"<input id='login-button' type='submit' value='Login'/>");
}
// (1) this does not work. chrome seems to require time after "onDomReady" to process
// the forms that are present on the page. if the form fields exist while that processing
// is going on, they will not generate the "Save Password?" prompt.
//create_login_form();
// (2) This works. chrome has obviously finished its "work" on the form fields by now so
// we can add our content to the form and, upon submit, it will prompt "Save Password?"
setTimeout(create_login_form,500);
});
</script>
</head>
<body>
<!-- Our dummy iframe where the form submits to -->
<iframe src="dummy.html" name="dummy" style="display: none"></iframe>
<form action="" method="post" target="dummy" id="login_form">
<!-- (3) fails. form content cannot be present on pageload -->
<!--
<input type='text' name='email'>
<input type='password' name='password'>
<input id='login-button' type='submit' value='Login'/>
-->
</form>
</body>
</html>
如果有人能够解释这里发生了什么,我会非常感激。
编辑:请注意,Chrome的“保存密码问题”已扩展到使用由Google开发的AngularJS的人员:here
答案 0 :(得分:23)
从Chrome 46开始,您不再需要iframe
黑客了!
只需确保原始登录表单不存在&#34;在推送状态或ajax请求之后,通过删除(或隐藏)表单或更改它的动作URL(没有测试但也应该工作)。还要确保同一页面中的所有其他表单都指向不同的操作URL,否则它们也会被视为登录表单。
看看这个例子:
<!doctype html>
<title>dynamic</title>
<button onclick="addGeneratedForms()">addGeneratedForms</button>
<script>
function addGeneratedForms(){
var div = document.createElement('div');
div.innerHTML = '<form class="login" method="post" action="login">\
<input type="text" name="username">\
<input type="password" name="password">\
<button type="submit">login</button> stay on this page but update the url with pushState\
</form>';
document.body.appendChild(div);
}
document.body.addEventListener('submit', function ajax(e){
e.preventDefault();
setTimeout(function(){
e.target.parentNode.removeChild(e.target); // Or alternatively just hide the form: e.target.style.display = 'none';
history.replaceState({success:true}, 'title', "/success.html");
// This is working too!!! (uncomment the history.xxxState(..) line above) (it works when the http response is a redirect or a 200 status)
//var request = new XMLHttpRequest();
//request.open('POST', '/success.html', true); // use a real url you have instead of '/success.html'
//request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
//request.send();
}, 1);
}, false);
</script>
如果您有兴趣,可以在this repo中找到更多示例。您可以使用节点node server.js
运行它。
也许还可以看到此提交的评论:https://github.com/mkurz/ajax-login/commit/c0d9503c1d2a6a3a052f337b8cad2259033b1a58
如果您需要帮助,请告诉我。
答案 1 :(得分:8)
在仔细研究这个问题之后,这是我的最终报告:
首先,问题中突出显示的问题实际上是红鲱鱼。我错误地将表单提交给iframe
(arty突出显示 - 但我没有连接点)。我对此问题的处理方法基于this example,其中一些其他相关答案也引用了。可以看到正确的方法here。基本上,action
的{{1}}应设置为form
的{{1}}(这正是@arty建议的那样)。
当你这样做时,问题中突出显示的特定问题就会消失,因为页面根本没有重新加载(这是有道理的 - 为什么在你提交src
时页面会重新加载?那应该让我失望了。无论如何,由于页面无法重新加载,因此无论您在iframe
之后等待显示表单多长时间,Chrome都不会要求您保存密码。
因此,提交至iframe
(正确)将永远不会导致Chrome要求您保存密码。 Chrome只会在包含该表单的页面重新加载时才会这样做(注意:与此处的旧帖子相反,如果动态创建表单,Chrome会要求您保存密码。)
因此,唯一的解决方案是在提交表单时强制重新加载页面。但是我们如何做到这一点并保持我们的AJAX / SPA结构完好无损?这是我的解决方案:
(1)将SPA分为两部分:(1)对于未登录的用户,(2)对于已登录的用户。对于那些拥有较大网站的人来说,这可能是不可行的。 我不认为这是一个永久的解决方案 - 请Chrome,请...修复此错误。
(2)我在表单上捕获了两个事件:onDomReady
和iframe
。特别是对于登录表单,我抓取onClickSaveButton
上的用户详细信息并进行AJAX调用以验证其信息。如果该信息通过,那么我手动调用onFormSubmit
在onClickSaveButton
,我确保在调用formName.submit()
之前未提交表单。
(3)表单提交到一个只重定向到onFormSubmit
文件的PHP文件
这种方法有两个好处:
(1)适用于Chrome。
(2)在Firefox上,用户现在只有在成功登录后才被要求保存密码(我个人总是觉得在出错时要求保存我的密码非常烦人。)
以下是相关代码(简化):
<强>的index.php 强>
onClickSaveButton
<强> MYCODE.JS 强>
index.php
<强> DUMMY.PHP 强>
<html>
<head>
<title>Chrome: Remember Password</title>
<!-- dependencies -->
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone.js"></script>
<!-- app code -->
<script type="text/javascript" src="mycode.js"></script>
<script>
$(function(){
createForm();
});
</script>
</head>
<body>
<div id='header'>
<h1>Welcome to my page!</h1>
</div>
<div id='content'>
<div id='form'>
</div>
</div>
</body>
</html>
编辑: mkurz的答案看起来很有希望。也许错误是固定的。
答案 2 :(得分:1)
您可以让Chrome(v39)显示密码保存提示,而无需重新加载。只需将表单提交给iframe,其中src是一个空白页面,不具有Content-Type: text/html
标题(省略标题或使用text/plain
两者似乎都有效。)< / p>
不知道这是一个错误,还是预期的行为。如果是前者,请保持安静: - )
答案 3 :(得分:0)
我正在使用Chrome 32.0。这两种方法在这里工作正常,无法理解为什么它最终会有所不同......
那就是说,我经常不得不使用setTimeout()几百毫秒来制作例如focus()按预期工作。那对你来说也许可以解决问题。在你的情况下:
setTimeout(display_login_form(),500)
答案 4 :(得分:0)
答案 5 :(得分:0)
我正在使用SPA应用程序,并且在仅通过AJAX请求传递用户凭据时,如何强制Chrome存储用户凭据存在相同的问题。因此,我使用navigator.credentials
来调用默认的Chrome对话框来存储网站的凭据。它像魅力一样起作用!
皮包骨头的例子。
HTML:
<form id="credential-form">
<input type="text" name="username" required autocomplete="username">
<input type="password" name="password" required autocomplete="current-password">
</form>
JS:
let credentialForm = document.getElementById('credential-form');
let credential = new PasswordCredential(credentialForm);
navigator.credentials.store(credential);
有关完整示例,请参见我在其中找到此解决方案的here。