Evitar que el navegador solicite recordar los datos de acceso en formulario de login

Al ingresar los datos de acceso en un sitio, el navegador propondrá almacenarlos excepto cuando se haya desactivado el guardado de contraseñas. En la mayoría de los casos es el comportamiento deseado, dado que el usuario puede decidir si quiere o no hacerlo.

Existen contadas ocasiones donde sería bueno que el sitio pudiera indicar al navegador que no realice esta esta propuesta (por ejemplo, el sitio web de un banco). Al momento de escribir esta publicación, no hay una forma simple. Hasta hace un tiempo los navegadores se comportaban de esta manera cuando se agregaba el atributo autocomplete=”off” al formulario, pero ya no más a partir de IE11, Chrome 34 y Firefox 30.

Igualmente, la seguridad en el acceso debería pasar por otro lado y no por evitar que el navegador recuerde la clave. El usuario puede tener otras aplicaciones o plugins del navegador donde se almacenen, hasta puede tenerlas anotadas en un papel.

Lo que les propongo es un formulario de login que NO fomenta al navegador a solicitar recordar el usuario y la clave, compatible con casi todas las versiones de Firefox, Chrome e Internet Explorer que pude probar. Tengan en cuenta que podría funcionar hasta que cambien las reglas nuevamente.

 

Tomaremos como base el formulario de login seguro que fomenta el recordar datos de acceso, al cual le realizaremos una serie de modificaciones:

Modificaciones sobre el formulario

Modificación 1: cambiamos el tipo de input submit por button. Esto es lo que evita que la mayoría de los navegadores proponga recordar la clave.

Modificación 2: agregamos al formulario el atributo autocomplete=”off”. Aunque no es esencial hacerlo, en versiones de los navegadores previas a las indicadas se contempla.

<form action="index.cgi" autocomplete="off" method="post" id="login_form" name="login_form">
  Email: <input type="text" name="e" id="email"  /><br />
  Password: <input type="password" name="p" id="password" /><br />
  <input type="hidden" name="ps" id="secret">
  <input type="button" value="Login" id="login_button" />
</form>

OBS: en el atributo action del formulario se indica el script que procesará los datos ingresados, en este caso index.cgi pero podría ser cualquiera.

Modificaciones sobre el código javascript

Modificación 3: establecemos el login_button como elemento a observar y el evento click (en lugar del submit del elemento login_form):

Event.observe( 'login_button', 'click', formProcess);

Modificación 4: agregaamos al final de la función formProcess la acción de submit del formulario

$('login_form').submit();

 

Un detalle de color: podemos darle el toque final capturando el Enter en los campos del formulario para procesarlo (esto se hace automáticamente cuando está presente el input submit).

Agregamos el atributo onkeypress en cada uno invocando a una nueva función checkEnter, la cual al detectar que se presionó Enter invoca la función de procesamiento del formulario:

Email: <input type="text" name="e" id="email" onkeypress="checkEnter(event)" /><br />
Password: <input type="password" name="p" id="password" onkeypress="checkEnter(event)" /><br />
function checkEnter(e){
  var codigoCaracter = (e && e.which) ? e.which : event.keyCode;
  if(codigoCaracter == 13) {
    formProcess();
  }
  else {
    return true;
  }
}

 

Formulario completo

A continuación les dejo el código del formulario completo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Test Site</title>
    <script type="text/javascript" src="sha512.js"></script>
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript">
      Event.observe(window, 'load', function(){
        Event.observe( 'login_button', 'click', formProcess);
      });
      function formProcess(){
        //agregar validaciones
        $('secret').value = hex_sha512($('password').value);
        $('password').value = '';
        $('login_form').submit();
      }
      function checkEnter(e){
        var codigoCaracter = (e && e.which) ? e.which : event.keyCode;
        if(codigoCaracter == 13) {
          formProcess();
        }
        else {
          return true;
        }
      }
    </script>
  </head>

  <body>
    <form action="index.cgi" autocomplete="off" method="post" id="login_form" name="login_form">
      Email: <input type="text" name="e" id="email" onkeypress="checkEnter(event)" /><br />
      Password: <input type="password" name="p" id="password" onkeypress="checkEnter(event)" /><br />
      <input type="hidden" name="ps" id="secret">
      <input type="button" value="Login" id="login_button" />
    </form>
  </body>
</html>
Anuncios

Formulario de login seguro que fomenta el recordar datos de acceso

A menos que hayamos desactivado el guardado de contraseñas, los navegadores propondrán almacenarla cuando formulario de login se presente en la pantalla.

La idea es plantear un formulario de login, ver los inconvenientes que se presentan y analizar soluciones, compatibles con casi todas las versiones de Firefox, Chrome e Internet Explorer (no puedo asegurar que lo que aquí se exponga funcione en todos los casos ni tampoco que sea para siempre).

Cuestiones genéricas a saber sobre el administrador de contraseñas de los navegadores

  • Aplica solamente en el ámbito del navegador que se esté usando
  • Solicita confirmación para guardar con los datos que están en los campos al momento de hacer el submit, principalmente cuando existe un input submit.
  • Tiene que haber un input password para que entre en acción.
  • Asocia el password al valor ingresado en el input de texto inmediatamente superior al de tipo password en el dominio en que se encuentra.
    • Si no lo hubiera, o bien no tuviera un valor, entonces se asocia el password directamente al dominio en que se encuentra.
  • En IE no se activa cuando el submit se realiza mediante javascript.

Formulario de login

<form action="index.cgi" method="post" id="login_form" name="login_form">
  Email: <input type="text" name="e" id="email" /><br />
  Password: <input type="password" name="p" id="password" /><br />
  <input type="submit" value="Login" id="login_button" />
</form>

OBS: en el atributo action del formulario se indica el script que procesará los datos ingresados, en este caso index.cgi pero podría ser cualquiera.

El problema en este caso es que la clave se comunica de manera plana.

  • Solución 1: Si se usara el protocolo HTTPS para la comunicación, la conexión de extremo a extremo estaría cifrada. Es lo más recomendado, pero vamos a considerar que no contamos con el certificado requerido para implementarlo y utilizamos HTTP común, a fin de hacer más interesante el ejemplo.
  • Solución 2: Cifrar la clave utilizando la función criptográfica que deseen. En el ejemplo utilizaremos SHA-512 que es bastante seguro y se puede obtener rápidamente mediante javascript.

OBS: Utilizaremos el framework Prototype de javascript para simplificar el código, pero pueden utilizar javascript puro o algún otro framework como jQuery.

Para implementar la solución 2, invocamos una función cuando se realice el submit del formulario para que lo procese. En ella ciframos la clave, de manera que cuando se comuniquen los datos, la misma viaje solamente de manera cifrada.

<script type="text/javascript">
  Event.observe(window, 'load', function(){
    Event.observe( 'login_form', 'submit', formProcess);
  });
  function formProcess(){
    //agregar validaciones
    $('password').value = hex_sha512($('password').value);
    return true;
  }
</script>

OBS: Se debe reemplazar el comentario //agregar validaciones por las validaciones del lado del cliente, correspondientes al procesamiento del formulario

Un detalle de color: tal como planteamos la solución, a la vista aparecen por un instante más caracteres en el campo justo antes de empezar a cargar la página después del submit (resultado del cifrado de la clave)

Mejora visual 1: podemos agregar un input hidden:

<input type="hidden" name="ps" id="secret">

donde guardamos la clave cifrada y luego borramos el contenido del campo password (de lo contrario viajaría la clana nuevamente)

$('secret').value = hex_sha512($('password').value);
$('password').value = '';

Entonces la clave ingresada desaparece por un instante justo antes de empezar a cargar la página después del submit.

Mejora visual 2: contamos la cantidad de caracteres de la clave ingresada y los reemplazamos por el caracter ‘x’:

$('secret').value = hex_sha512($('password').value);
var pass_len = $('password').value.length;
$('password').value = Array(pass_len+1).join("x");

A la vista, no cambia nada cuando hacemos el submit, pero hemos cifrado la clave.

OBS: Si pensaron hacer un disable del input password es posible que en ciertos navegadores no proponga recordarles la contraseña (ej. chrome). La mejora 2, se podría realizar también agregando OTRO input hidden y disabled (ubicado inmediatamente despúes de password) que se complete con la clave antes de borrarla, y que el procesamiento del formulario oculte el input password y se ponga visible el disabled.

Formulario completo

A continuación les dejo el código del formulario completo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Test Site</title>

    <script type="text/javascript" src="sha512.js"></script>
    <script type="text/javascript" src="prototype.js"></script>

    <script type="text/javascript">
      Event.observe(window, 'load', function(){
        Event.observe( 'login_form', 'submit', formProcess);
      });
      function formProcess(){
        //agregar validaciones
        $('secret').value = hex_sha512($('password').value);
        var pass_len = $('password').value.length;
        $('password').value = Array(pass_len+1).join("x");
        return true;
      }
    </script>
  </head>
  <body>
    <form action="index.cgi" method="post" id="login_form" name="login_form">
      Email: <input type="text" name="e" id="email" /><br />
      Password: <input type="password" name="p" id="password" /><br />
      <input type="hidden" name="ps" id="secret">
      <input type="submit" value="Login" id="login_button" />
    </form>
  </body>
</html>