Validación de contraseña de JavaScript

Como he visto toneladas de solicitudes de ayuda para la validación de contraseñas en regexadvice.com (donde paso el rato de vez en cuando), he escrito una función de validación de contraseñas de JavaScript más general. Es razonablemente sencillo y cubre los requisitos de validación que he encontrado con más frecuencia. Además, si no se adapta exactamente a sus necesidades, su funcionalidad se puede aumentar pasándole funciones personalizadas y expresiones regulares.

Estos son los tipos de validación compatibles listos para usar. Todas son opcionales, lo que significa que todas las contraseñas están permitidas de forma predeterminada.

  • Longitud mínima y máxima.
  • Mínimo n caracteres en minúsculas (a–z).
  • Mínimo n caracteres en mayúsculas (A–Z).
  • Mínimo n caracteres combinados a–z y A–Z.
  • Mínimo n caracteres numéricos (0–9).
  • Mínimo n caracteres especiales (caracteres que no sean a–z, A–Z y 0–9).
  • Prohibir palabras particulares (probado sin distinción entre mayúsculas y minúsculas).
  • Prohibir n Secuencias de caracteres de longitud (por ejemplo, "abc", "XYZ" o "789", con una longitud de secuencia de 3; no se aplica a los caracteres especiales).
  • Prohibir n -longitud de secuencias de caracteres qwerty (por ejemplo, "qwerty" o "asdf", con una longitud de secuencia de 4; no se aplica a los caracteres especiales).
  • Prohibición de caracteres secuenciales e idénticos (por ejemplo, "aa" o "!!").
  • Utilice expresiones regulares personalizadas (probadas con RegExp.prototype.test ) y funciones (la contraseña se proporciona como primer argumento y se espera un valor booleano a cambio).

He aquí un ejemplo de cómo se puede utilizar:

var password = "password";
var passed = validatePassword(password, {
	length:   [8, Infinity],
	lower:    1,
	upper:    1,
	numeric:  1,
	special:  1,
	badWords: ["password", "steven", "levithan"],
	badSequenceLength: 4
});
// passed: false

Lo anterior requiere que password tiene al menos ocho caracteres; tiene al menos un carácter en minúscula, mayúscula, numérico y especial; no incluye las palabras "contraseña", "steven" o "levithan"; y no incluye una secuencia alfanumérica de cuatro o más caracteres (por ejemplo, "1234").

Aquí está el código (no hay dependencias de bibliotecas externas):

/*
	Password Validator 0.1
	(c) 2007 Steven Levithan <stevenlevithan.com>
	MIT License
*/

function validatePassword (pw, options) {
	// default options (allows any password)
	var o = {
		lower:    0,
		upper:    0,
		alpha:    0, /* lower + upper */
		numeric:  0,
		special:  0,
		length:   [0, Infinity],
		custom:   [ /* regexes and/or functions */ ],
		badWords: [],
		badSequenceLength: 0,
		noQwertySequences: false,
		noSequential:      false
	};

	for (var property in options)
		o[property] = options[property];

	var	re = {
			lower:   /[a-z]/g,
			upper:   /[A-Z]/g,
			alpha:   /[A-Z]/gi,
			numeric: /[0-9]/g,
			special: /[\W_]/g
		},
		rule, i;

	// enforce min/max length
	if (pw.length < o.length[0] || pw.length > o.length[1])
		return false;

	// enforce lower/upper/alpha/numeric/special rules
	for (rule in re) {
		if ((pw.match(re[rule]) || []).length < o[rule])
			return false;
	}

	// enforce word ban (case insensitive)
	for (i = 0; i < o.badWords.length; i++) {
		if (pw.toLowerCase().indexOf(o.badWords[i].toLowerCase()) > -1)
			return false;
	}

	// enforce the no sequential, identical characters rule
	if (o.noSequential && /([\S\s])\1/.test(pw))
		return false;

	// enforce alphanumeric/qwerty sequence ban rules
	if (o.badSequenceLength) {
		var	lower   = "abcdefghijklmnopqrstuvwxyz",
			upper   = lower.toUpperCase(),
			numbers = "0123456789",
			qwerty  = "qwertyuiopasdfghjklzxcvbnm",
			start   = o.badSequenceLength - 1,
			seq     = "_" + pw.slice(0, start);
		for (i = start; i < pw.length; i++) {
			seq = seq.slice(1) + pw.charAt(i);
			if (
				lower.indexOf(seq)   > -1 ||
				upper.indexOf(seq)   > -1 ||
				numbers.indexOf(seq) > -1 ||
				(o.noQwertySequences && qwerty.indexOf(seq) > -1)
			) {
				return false;
			}
		}
	}

	// enforce custom regex/function rules
	for (i = 0; i < o.custom.length; i++) {
		rule = o.custom[i];
		if (rule instanceof RegExp) {
			if (!rule.test(pw))
				return false;
		} else if (rule instanceof Function) {
			if (!rule(pw))
				return false;
		}
	}

	// great success!
	return true;
}

Puedes descargarlo aquí .

Avíseme si tiene alguna solicitud de función u otras sugerencias sobre cómo mejorarla, o si necesita ayuda para escribir reglas personalizadas para ella.