代码之家  ›  专栏  ›  技术社区  ›  Eric

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

  •  124
  • Eric  · 技术社区  · 15 年前

    嘿,我正在开发一个Web应用,它有一个登录对话框,工作原理如下:

    1. 用户点击“登录”
    2. 登录表单html使用ajax加载,并在页面的div中显示
    3. 用户在字段中输入user/pass并单击submit。它不是一个 <form> --用户/通行证通过ajax提交
    4. 如果用户/通行证正常,页面将重新加载已登录的用户。
    5. 如果user/pass不正确,则页面不会重新加载,但div中会显示错误消息,用户可以重试。

    问题是:浏览器从不提供通常的“保存此密码”?“是/从不/现在不”提示它为其他站点所做的操作。

    我试着把 <div> 在里面 <形式& gt; 带有“autocomplete=”的标记,但这没有区别。

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

    谢谢 埃里克

    另外,我的问题是,我肯定是在使用存储密码的浏览器,而且我从来没有点击过“Never for this site”……这是一个技术问题,因为浏览器没有检测到它是一个登录表单,而不是操作员错误:-)

    18 回复  |  直到 9 年前
        1
  •  63
  •   dragonfire user1366660    10 年前

    我找到了这个问题的完整答案。(我已经在chrome 27和firefox 21中测试过了)。

    有两件事要知道:

    1. 触发“保存密码”,然后
    2. 还原保存的用户名/密码

    1。触发“保存密码”:

    为了 火狐21 当检测到存在包含输入文本字段和输入密码字段的表单时,将触发“保存密码”。所以我们只需要利用

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

    someFunctionForLogin() ajax是否在 event.preventDefault() 由于提交表单而阻止原始重定向。

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

    为了 铬27 ,“保存密码”被触发 之后 它通过提交包含输入文本字段的表单重定向到页面 属性名为'username' 并输入密码字段 属性名为“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>
    

    类型为“button”的按钮将使单击该按钮时不提交表单。 然后,将函数绑定到用于ajax登录的按钮。最后,打电话 $('#loginForm').submit(); 重定向到登录页。如果登录页是当前页,则可以将“signed in.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='关闭' 将使将用户名/密码还原到loginform失败,因为您不允许它“自动完成”用户名/密码。

        2
  •  36
  •   dragonfire user1366660    10 年前

    使用A 按钮 登录:

    如果你使用 type="button" 用一个 onclick 要使用的登录处理程序 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>
    

    从这个表格开始 没有提交按钮 并且没有操作字段,浏览器将不提供保存密码的功能。


    使用A 提交 登录按钮:

    但是,如果将按钮更改为 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
    }
    
        3
  •  15
  •   TK421    13 年前

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

    这一切都源于我的登录表单被动态地注入页面(使用backbone.js)。一旦我将登录表单直接嵌入index.html文件中,所有的操作都像一个符咒。

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

        4
  •  12
  •   Bert F    14 年前

    这个解决方案对我有用,埃里克在CodingForums上发布了


    之所以不提示,是因为浏览器需要将页面物理地刷新回服务器。你能做的一个小技巧是用表单执行两个操作。第一个动作是提交调用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

        5
  •  11
  •   Michal Roharik    12 年前

    有一个 最终的 强制所有浏览器(测试:chrome 25、safari 5.1、ie10、firefox 16)使用 JQuery 阿贾克斯 请求:

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

    希望对某人有帮助。

        6
  •  7
  •   Community CDub    8 年前

    我试过 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中测试过。

        7
  •  4
  •   Community CDub    8 年前

    浏览器可能无法检测到您的表单是登录表单。根据年的一些讨论 this previous question ,浏览器将查找类似于 <input type="password"> . 您的密码表单域的实现与此类似吗?

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

        8
  •  1
  •   Simon Lang    12 年前

    我花了很多时间阅读这条线索上的各种答案,对我来说,这实际上是有点不同的东西(相关,但不同)。在mobile safari(ios设备)上,如果在加载页面时隐藏登录表单,则不会显示提示(显示表单后提交)。您可以使用以下代码进行测试,该代码在页面加载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>
    
        9
  •  1
  •   David Rettenbacher    10 年前

    以下代码在上测试

    • 铬39.0.2171.99m:工作
    • 安卓Chrome 39.0.2171.93:工作
    • android股票浏览器(android 4.4):不工作
    • Internet Explorer 5+(模拟):工作
    • Internet Explorer 11.0.9600.17498/更新版本:11.0.15:工作
    • Firefox35.0:工作

    JS Fiddle:
    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资源管理器 需要“密码”字段 显示存储密码对话框
    • 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
        });
    };
    

    评论

    • “帐户/登录”设置 曲奇饼 如果成功
    • 页面重定向 (“手动”由js代码启动)似乎是必需的。我还测试了一个iframe帖子,但我没有成功。
        10
  •  1
  •   mwieczorek    9 年前

    我为prototype.js用户找到了一个相当优雅的解决方案(或hack,不管怎样),它是使用prototype的最后一个坚持者之一。简单地替换相应的jquery方法就可以了。

    首先,确保有一个 <form> 标签和一个带有类名的submit按钮,可以稍后引用(在本例中 faux-submit )嵌套在样式设置为的元素中的 display:none ,如下所示:

    <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 使用隐藏输入按钮的类(如上所述, 假提交 ):

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

    这在firefox 43和chrome 50中被测试为有效。

        11
  •  0
  •   Dave.Sol    15 年前

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

        12
  •  0
  •   maxisam    12 年前

    在@michal roharik的答案中添加更多信息。

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

    前任。

    $(form).attr('action', ReturnPath);
    form.submitted = false;
    form.submit(); 
    
        13
  •  0
  •   Igor    11 年前

    我也遇到过类似的问题,登录是用ajax完成的,但是如果表单(login form)是用ajax提交的,浏览器(firefox、chrome、safari和ie 7-10)不会提供保存密码的功能。

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

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

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

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

    不会提供在IE中保存密码的功能(尽管它在其他浏览器中也有效)。

        14
  •  -1
  •   Buhake Sindi Tesnep    15 年前

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

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

    希望这能给人以启发。-)

        15
  •  -1
  •   Jack Marchetti    15 年前

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

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

        16
  •  -1
  •   harriyott Erik Funkenbusch    12 年前

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

        17
  •  -1
  •   ShelatoBaboon    11 年前

    这对我来说工作得更好,因为它是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>
    
        18
  •  -2
  •   Mandrig    15 年前

    使用饼干可能是最好的方法。

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

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