码农家园

关闭
导航

关于ajax:如何让浏览器提示保存密码?


ajaxbrowserfirefoxlogin

How can I get browser to prompt to save password?

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

  • 用户点击"登录"
  • 登录表单HTML使用AJAX加载并显示在页面上的DIV中
  • 用户输入用户/传递字段并单击提交。它不是

    - 用户/通过AJAX提交
  • 如果用户/通行证没问题,则页面会在用户登录时重新加载。
  • 如果用户/传递不好,页面不会重新加载,但DIV中会出现错误消息,用户可以再次尝试。
  • 这是问题所在:浏览器从未提供通常的"保存此密码?是/从不/不立即"提示它为其他网站提供的。

    我尝试用"autocomplete ='on'"包装

    标签中的,但这没有任何区别。

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

    谢谢
    埃里克

    附:添加到我的问题,我肯定使用存储密码的浏览器,我从来没有点击"从不为这个网站"...这是一个技术问题,浏览器没有检测到它是一个登录表单,而不是运算符错误:-)

    相关讨论

    • 不要忘记并非所有浏览器都可以存储密码。
    • mabe浏览器提供保存您的用户/通行证,然后您点击"再也不要问了!"?
    • 相关:stackoverflow.com/questions/6142725/


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

    有两件事需要知道:

  • 触发'保存密码',然后
  • 恢复保存的用户名/密码
  • 1.触发'保存密码':

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

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

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

    如果您只处理Firefox,上述解决方案就足够了,但它在Chrome 27中不起作用。然后您将询问如何在Chrome 27中触发"保存密码"。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <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>

        $('#loginButton').click(someFunctionForLogin);
        function someFunctionForLogin(){
            if(/*ajax login success*/) {
                $('#loginForm').submit();
            }
            else {
                //do something to show login fail(e.g. display fail messages)
            }
        }

    按下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'

    1
    <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
    • 这不适用于IE 9
    • 很多用户使用ENTER键提交表单,因为当用户提交表单时你有prevented default,什么都不会发生,那就是糟糕的用户体验。您可以在提交时检查输入密钥keycode,但是您将再次进入乞讨...
    • Chrome 46修复了错误的行为 - 不再需要解决方法了。请参阅stackoverflow.com/a/33113374/810109
    • 是否有一些文档可以让我看到Google Chrome"允许"name - 属性值?目前我的字段名为identity,chrome没有提示保存密码对话框
    • 不能可靠地工作,如果您从Javascript提交,某些浏览器不会触发"记住"功能。
    • Safari是我的问题浏览器。


    使用按钮登录:

    如果使用type="button"和onclick处理程序使用ajax登录,则浏览器将不提供保存密码。

    1
    2
    3
    4
    5
    <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"并处理提交,则浏览器将提供保存密码。

    1
    2
    3
    4
    5
    <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:

    1
    2
    3
    4
    5
    6
    7
    8
    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因为它有效但被接受的答案没有(至少对我来说)。谢谢spetson!
    • 在IE中也适合我。我现在可以吻你了!
    • @Bigood它适用于Firefox
    • 不工作....
    • 也为我工作.. :)
    • 这是正确的,也是问题最优雅的解决方案。
    • 它的工作原理是因为我只需复制第二个代码并通过检查元素将其粘贴到登录页面,在该页面上新添加的文件中输入用户名/密码然后按登录然后它会提示我保存用户/密码。然后我刷新页面瞧,它提示我选择已经保存的用户/通行证;)


    我一直在努力解决这个问题,最后我能够找到问题以及导致失败的原因。

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

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

    相关讨论

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


    这个解决方案适用于我,由Eric发布在编码论坛上

    The reason why it does not prompt it is because the browser needs the page to phyiscally to refresh back to the server. A little trick you can do is to perform two actions with the form. First action is onsubmit have it call your Ajax code. Also have the form target a hidden iframe.

    码:

    1
    2
    <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

    相关讨论

    • 作为备注,我发现如果表单已提交给自己,则Chrome 11不提供保存凭据。因此,您需要将action设置为某个虚拟页面。
    • 这将在URL中发送密码明文作为get请求。如果方法更改为POST,Firefox(16)将在新选项卡中打开以前隐藏的框架。在Android 4上的chrome也是如此::-(
    • Chrome 46修复了错误的行为 - 不再需要iframe变通办法。请参阅stackoverflow.com/a/33113374/810109


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

    JS:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    $(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:

    1
    2
    3
    4
    5
    6
    7
    <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的成功回调中再次提交表单,以便浏览器捕获它并显示请求密码保存。
    您还可以添加一些错误处理程序等。

    希望它对某人有所帮助。

    相关讨论

    • 这实际上会使HTTP到达login.php?username=username&password=password,这首先取消了保存密码的全部目的
    • Wooooooooooooooooooooooooooooooooooooooooooooooh!这对我有用;)非常感谢!
    • 是的,添加event listener以形成并添加event.preventDefault()加上event.stopPropagation()


    我尝试了spetson的答案,但这对我来说不适用于Chrome 18.我的工作是为iframe添加一个加载处理程序而不是中断提交(jQuery 1.7):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        Please log in
        <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>

    <iframe id="loginframe" name="loginframe"></iframe>

    getSessions()执行AJAX调用,如果失败则显示loginForm div。 (如果未对用户进行身份验证,则Web服务将返回403)。

    测试也适用于FF和IE8。

    相关讨论

    • 这对我有用,+1 w00t。
    • 我在Chrome中尝试了这种方法,除非操作页面(在您的示例中为/login)返回了一些文本或其他可见内容,否则它将无效。
    • 很高兴知道,谢谢@stephenbunch
    • Chrome 46修复了错误的行为 - 不再需要iframe变通办法。请参阅stackoverflow.com/a/33113374/810109


    浏览器可能无法检测到您的表单是登录表单。根据上一个问题中的一些讨论,浏览器会查找看起来像的表单字段。您的密码表单字段是否与此类似?

    编辑:为了回答下面的问题,我认为Firefox会通过form.elements[n].type =="password"检测密码(遍历所有表单元素),然后通过在密码字段之前的文本字段的表单元素向后搜索来检测用户名字段(此处有更多信息) 。据我所知,您的登录表单需要是

    的一部分,否则Firefox将无法检测到它。

    相关讨论

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


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

    JS:

    1
    2
    3
    4
    5
    $(function() {
      setTimeout(function() {
        $('form').fadeIn();
      }, 5000);
    });

    HTML:

    1
    2
    3
    4
    5
    <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>

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

    首先,确保有一个

    标签和一个带有类名的提交按钮,该按钮稍后可以引用(在本例中为faux-submit),它嵌套在一个样式设置为display:none的元素中,如下图所示:

    1
    2
    3
    4
    5
    6
    7
    8
    <form id="login_form" action="somewhere.php" method="post">
        <input type="text" name="login" />
        <input type="password" name="password" />
       
            <input class="faux-submit" type="submit" value="Submit" />
       
        <button id="submit_button">Login</button>
    </form>

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

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

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

    1
    2
    3
    4
    5
    document.observe('submit', function(event) {
        if (event.findElement(".faux-submit")) {
            event.stop();
        }
    });

    这在Firefox 43和Chrome 50中进行了测试。


    以下代码已经过测试

    • Chrome 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/

    邮码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    // 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登录代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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
        });
    };

    备注

    • 如果成功,"account / login"会设置cookie
    • 页面重定向(由js-code"手动"启动)似乎是必需的。我也测试了一个iframe帖子,但我没有成功。
    相关讨论

    • 在Chrome 71中不起作用。
    • 可以确认,不适用于最新的Chrome


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

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

    恩。

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


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

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

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

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

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

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


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


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

    1
    2
    3
    4
    5
    6
    7
    <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" />
     Login
    </form>

    事实是,你不能强迫浏览器询问。我确定浏览器有自己的算法来猜测你是否输入了用户名/密码,比如查找type="password"的输入,但你无法设置任何强制浏览器。

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

    相关讨论

    • 你建议饼干?
    • 我说要加密你存储在他们中的任何东西。
    • 饼干?那是等待发生的坏主意


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

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

    希望这可以暗示。 :-)

    相关讨论

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


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


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

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

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


      Copyright ©  码农家园 联系:[email protected]