Validando senhas fortes com Ruby on Rails e JavaScript


Leia em 2 minutos

Em muitos projetos, é importante que o usuário informe senhas que tenham um mínimo de complexidade, evitando que sejam facilmente quebradas. Existem muitas soluções feitas em JavaScript, mas não encontrei nenhuma que fosse boa o bastante no backend.

Pensando nisso, criei uma gem chamada Password Strength que faz validação de diversos padrões, a fim de identificar senhas que sejam fracas. Ela é composta por 2 módulos: ActiveRecord e JavaScript.

A validação da senha é feita com base nas seguintes regras:

Cada uma dessas regras recebe uma pontuação negativa ou positiva, que irá influenciar no resultado final. Assim, com base nessas regras, podemos classificar as seguintes senhas:

Instalação

Para instalar, basta executar o comando

sudo gem install password_strength

Agora, configure seu aplicativo para carregá-la. No Rails 2, basta adicionar a linha abaixo ao seu arquivo environment.rb.

config.gem "password_strength"

No Rails 3, adicione a linha abaixo ao arquivo Gemfile.

gem "password_strength"

Se quiser usar o plugin para jQuery, você também precisará dos arquivos password_strength.js e jquery.strength.js.

Usando na prática

O Password Strength permite que você valide senhas sem a necessidade de usar o ActiveRecord.

strength = PasswordStrength.test("johndoe", "mypass")
#=> return an object

strength.good?
#=> status == :good

strength.weak?
#=> status == :weak

strength.strong?
#=> status == :strong

strength.status
#=> can be :weak, :good, :strong

strength.valid?(:strong)
#=> status == :strong

strength.valid?(:good)
#=> [:good, :strong].include?(status)

Muito simples!

ActiveRecord

O Password Strength possui suporte para ActiveRecord 2.3+ (foi testado em 2.3.5 e 3.0.0-beta).

No seu modelo, adicione a validação validates_strength_of.

class User < ActiveRecord::Base
  validates_strength_of :password
end

Por padrão, as opções serão :level => :good, :with => :username. A opção :level define a complexidade mínima requerida e pode ser :good, :strong ou :weak (é desnecessário dizer que a última opção não faz o menor sentido, já que qualquer senha será aceita). Já a opção :with define qual o atributo que deverá ser usado na comparação da senha. Se quiser, pode definir um outro atributo:

validates_strength_of :password, :with => :email

Também é possível proibir senhas que usem determinados caracteres por completo com a opção :exclude. Podemos, por exemplo, evitar que senhas contendo a string asdf sejam usadas:

validates_strength_of :password, :exclude => /asdf/i

Alternativamente, você pode definir uma lista de strings que não devem ser utilizadas:

validates_strength_of :password, :exclude => %w[ asdf qwert zxcv ]

JavaScript

No HTML, adicione os arquivos que você baixou.

<script src="jquery-1.4.2.js" type="text/javascript"></script>
<script src="password_strength.js" type="text/javascript"></script>
<script src="jquery.strength.js" type="text/javascript"></script>

Se você não usa jQuery, pode usar apenas o arquivo password_strength.js e criar o seu próprio adaptador.

A API do JavaScript é essencialmente a mesma, inclusive com as mesmas regras de verificação. Veja:

var strength = PasswordStrength.test("johndoe", "mypass");
strength.isGood();
strength.isStrong();
strength.isWeak();
strength.isValid("good");

Você também pode usar a opção :exclude mas, no momento, apenas expressões regulares são aceitas.

var strength = PasswordStrength.test("johndoe", "password with whitespaces", {exclude: /\s/});
strength.isInvalid();

Se você usa jQuery, pode utilizar o plugin que já vem com o Password Strength.

$.strength("#username", "#password");

A definição acima irá utilizar o campo #username e #password para fazer a validação da senha. Conforme a senha é digitada, uma imagem é colocada ao lado do campo de senha. Por padrão, as imagens utilizadas são /images/{weak,good,strong}.png. Se você quiser, pode alterar esses caminhos:

$.strength.weakImage = "/weak.png";
$.strength.goodImage = "/good.png";
$.strength.strongImage = "/strong.png";

Você também pode sobrescrever o callback padrão.

$.strength("#username", "#password", function(username, password, strength){
	// do whatever you want
});

Se você quiser sobrescrever o callback globalmente, pode fazê-lo da seguinte maneira:

$.strength.callback = function(username, password, strength) {
	// do whatever you want
};

Qualquer dúvida, mande um comentário!