Luchando contra el recordador de contraseñas del Firefox

Posted on Friday, January 1, 2010 in Programación web

Luchando contra el recordador de contraseñas del Firefox

La situación es la siguiente: una página web en la que tras acceder con un nombre de usuario y una contraseña se puede dar de alta a nuevos usuarios y un usuario que usa Mozilla Firefox con la opción de recordar contraseñas.

El caso: el usuario crea una nueva cuenta o bien accede con una cuenta y luego edita esa misma cuenta desde otra cuenta

El problema: Al crear la nueva cuenta el Firefox le rellenará los campos con el nombre y contraseña de la cuenta actual. Al editar la cuenta el Firefox le rellenará los campos con el nombre y contraseña que se están editando que también están en el recordador de contraseñas, si el usuario no edita con la intención de cambiar la contraseña no se fija en que sólo el primero de los dos campos "Contraseña" y "Repetir contraseña" tiene contenido por lo que al darle a guardar le dará el error de "Las dos contraseñas no coinciden".

La solución:

  • Primer intento: cambiar el nombre del campo de contraseña en el formulario de edición y creación de usuarios para que no coincida con el nombre del formulario de login:

    Acceso:

    <tr>
      <td><label for="user">Username:</label></td>
      <td><input name="user" id="user" type="text"></td>
    </tr>
    <tr>
      <td><label for="pass">Password:</label></td>
      <td><input name="pass" id="pass" type="password"></td>
    </tr>
    

    Añadir/editar usuario:

    <tr>
      <td><label for="edituser">Username:</label></td>
      <td><input name="edituser" id="edituser" type="text"></td>
    </tr>
    <tr>
      <td><label for="editpass">Password:</label></td>
      <td><input name="editpass" id="editpass" type="password"></td>
    </tr>
    <tr>
      <td><label for="editpass2">Repeat Password:</label></td>
      <td><input name="editpass2" id="editpass2" type="password"></td>
    </tr>
    

    Problema: mismo resultado, el nombre del campo no era el motivo por el que el Firefox sólo rellenaba el primer password y no el segundo, parece que sólo busca el primer campo tipo password que encuentre.

  • Segundo intento: ocultar los campos de contraseña y en su lugar mostrar la opción de cambiar las contraseñas que al seleccionarla despliegue los campos de contraseña.

    <script type="text/javascript;">
    <!--
      function show_pass()
      {
        document.getElementById('tr_chpass').style.display = 'none';
        document.getElementById('tr_pass').style.display = 'table-row';
        document.getElementById('tr_pass2').style.display = 'table-row';
      }
    //-->
    </script>
    
    <!-- ... -->
    
    <tr>
      <td><label for="user">Username:</label></td>
      <td><input name="user" id="user" type="text"></td>
    </tr>
    <tr id="tr_chpass">
      <td><label for="chpass">Password:</label></td>
      <td><span
          id="chpass"
          style="cursor: pointer; color: blue; border-bottom: 1px dotted blue;"
          onclick="show_pass();">
          Change password</span>
      </td>
    </tr>
    <tr style="display: none;" id="tr_pass">
      <td><label for="pass">Password:</label></td>
      <td><input name="pass" id="pass" type="password"></td>
    </tr>
    <tr style="display: none;" id="tr_pass2">
      <td><label for="pass2">Repeat password:</label></td>
      <td><input name="pass2" id="pass2" type="password"></td>
    </tr>
    

    Problema: mismo comportamiento

  • Tercer intento: no incluir los inputs de la contraseña en el formulario, generarlos por JavaScript añadiéndolos a la tabla con element.innerHTML

    <script type="text/javascript;">
    <!--
      function show_pass()
      {
        var tr_chpass = document.getElementById("tr_chpass");
        tr_chpass.style.display = "none";
        var tr_pass = document.createElement('tr');
        tr_pass.innerHTML =
            "<td><label for='pass'>Password:<\/label><\/td>" +
            "<td><input type='password' name='pass' id='pass'><\/td>";
        var tr_pass2 = document.createElement('tr');
        tr_pass2.innerHTML =
            "<td><label for='pass2'>Repeat Password:<\/label><\/td>" +
            "<td><input type='password' name='pass2' id='pass2'><\/td>";
        var parent_table = tr_chpass.parentNode;
        parent_table.insertBefore(tr_pass, tr_chpass);
        parent_table.insertBefore(tr_pass2, tr_chpass);
      }
    //-->
    </script>
    
    <!-- ... -->
    
    <tr>
      <td><label for="user">Username:</label></td>
      <td><input name="user" id="user" type="text"></td>
    </tr>
    <tr id="tr_chpass">
      <td><label for="chpass">Password:</label></td>
      <td><span
          id="chpass"
          style="cursor: pointer; color: blue; border-bottom: 1px dotted blue;"
          onclick="show_pass();">
          Change password</span>
      </td>
    </tr>
    

    Problema: parece que Firefox no renderiza correctamente las tablas generadas con innerHTML ya que el resultado es el siguiente:

  • Cuarto y último intento: no incluir los inputs de la contraseña en el formulario, generarlos por JavaScript añadiéndolos a la tabla con element.insertBefore()

    <script type="text/javascript;">
    <!--
      function show_pass()
      {
        document.getElementById("tr_chpass").style.display = "none";
        var tr_pass = document.createElement('tr');
        var tr_pass2 = document.createElement('tr');
        var td_label_pass = document.createElement('td');
        td_label_pass.innerHTML = "<label for='pass'>Password:<\/label>";
        var td_input_pass = document.createElement('td');
        td_input_pass.innerHTML = "<input type='password' name='pass' id='pass'>";
        var td_label_pass2 = document.createElement('td');
        td_label_pass2.innerHTML = "<label for='pass2'>Repeat Password:<\/label>";
        var td_label_pass2 = document.createElement('td');
        tr2td2.innerHTML = "<input type='password' name='pass2' id='pass2'>";
        tr_pass.insertBefore(td_label_pass, null);
        tr_pass.insertBefore(td_input_pass, null);
        tr_pass2.insertBefore(td_label_pass2, null);
        tr_pass2.insertBefore(td_input_pass2, null);
        var tr_chpass = document.getElementById("chpass_row");
        var parent_table = tr_chpass.parentNode;
        parent_table.insertBefore(tr_pass, tr_chpass);
        parent_table.insertBefore(tr_pass2, tr_chpass);
      }
    //-->
    </script>
    
    <!-- ... -->
    
    <tr>
      <td><label for="user">Username:</label></td>
      <td><input name="user" id="user" type="text"></td>
    </tr>
    <tr id="tr_chpass">
      <td><label for="chpass">Password:</label></td>
      <td><span
          id="chpass"
          style="cursor: pointer; color: blue; border-bottom: 1px dotted blue;"
          onclick="show_pass();">
          Change password</span>
      </td>
    </tr>