Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Validação de Senha

Olá, finalizei o curso de regex pois tinha um desafio para resolver e precisava aprender a como fazer a validação de uma senha. No início do curso eu não sabia nada sobre expressões regulares, mas ao finalizar o curso consegui fazer o desafio que eu tinha funcionar. Entretanto, não sei se a forma que eu fiz foi uma das melhores, ainda tenho muitas dúvidas sobre como produzir um bom código. Dito isto, o desafio que eu tinha inicialmente era o seguinte: --> Validar uma senha: implementar uma função definida como* validaComplexidade**(valor*) que deve receber uma String e implementar algumas validações para garantir a complexidade de uma senha.

  • deve ter de 8 a 32 caracteres
  • deve ter, no mínimo, uma letra maiúscula, uma letra minúscula e um número;
  • não pode ter caractere de pontuação, acentuação ou espaço

fiz o a função da seguinte forma

public void validaComplexidade(String valor) {
        Pattern pattern = Pattern.compile("(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\\S+$)[^@\\.;\\(\\)\\_!?&\\-\\+\\^\\´âêôáéíóúÂÊÔÁÉÍÓÚ]+$");
        Matcher matcher = pattern.matcher(valor);
        if (valor.length() < 8 && valor.length() > 32) {
            System.out.println("Senha deve conter de 8 a 32 caracteres");
        } else {
            if (matcher.find()) {
                System.out.println("senha valida");
            } else {
                System.out.println("senha invalida, verifique se ha espacos ou caracteres improprios");
            }
        }
    }
}

--> o Código acima foi o que eu consegui fazer, no entanto, achei a minha regex um pouco longa demais... não sei se é comum ficar assim..

  • O que eu gostaria de saber é: Alguém tem alguma sugestão do que eu poderia melhorar?
5 respostas
solução!

Olá Milena, tudo bem?

Acho muito bom que você esteja tentando se desafiar a escrever suas próprias expressões regulares. Programação é isso aí... é prática mesmo! Mas bora lá para sua questão!

Pelos requisitos que você descreveu, basicamente a senha deve:

  1. Aceitar apenas caracteres alfanuméricos: A-Z, a-z, 0-9
  2. Ter entre 8 e 32 caracteres ao todo
  3. Exigir que a senha tenha ao menos: 1 letra maiúscula, 1 minúscula e 1 número.

Sendo assim sugiro a seguinte expressão regular: (?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]{8,32}$

Basicamente ela diz o seguinte:

  • Ela verifica se há ao menos uma ocorrência de letra minúscula no valor checado: (?=.*[a-z])
  • Em seguida faz a mesma verificação se há ocorrência de letra maiúscula: (?=.*[A-Z])
  • E por fim, verifica se há ao menos um número: (?=.*[0-9])
  • Até aí está igualzinho o que você fez, eu só adicionei mesmo a parte final [a-zA-Z0-9]{8,32}$ que diz que o conteúdo deve ser alfanumérico apenas e a quantidade de caracteres deve ser, necessariamente entre 8 e 32 caracteres.

Sendo assim, o código poderia ser escrito da seguinte forma:

public void validaComplexidade(String valor) {
    Pattern pattern = Pattern.compile("(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]{8,32}$");
    Matcher matcher = pattern.matcher(valor);
    if (matcher.find()) {
        System.out.println("senha valida");
    } else {
        System.out.println("senha invalida, verifique se ha espacos ou caracteres improprios");
    }
}

Repare que até mesmo o if que verifica a quantidade de caracteres pode ser removido já que a expressão regular já checa a quantidade de caracteres e já indicaria que a senha está inválida.

Por outro lado, se quiser gerar uma mensagem de erro específica para a checagem de quantidade de caracteres (como você fez), então o código ficaria assim:

public void validaComplexidade(String valor) {
        Pattern pattern = Pattern.compile("(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$");
        Matcher matcher = pattern.matcher(valor);
        if (valor.length() < 8 || valor.length() > 32) {
            System.out.println("Senha deve conter de 8 a 32 caracteres");
        } else {
            if (matcher.find()) {
                System.out.println("senha valida");
            } else {
                System.out.println("senha invalida, verifique se ha espacos ou caracteres improprios");
            }
        }
    }

Ao invés de colocarmos uma limitação de quantidade de caracteres na expressão regular, deixamos essa quantidade livre (+ indicando UMA ou MAIS ocorrências) e deixamos o trabalho de verificação com o Java. Note que o correto aqui é utilizarmos o operador lógico OU (||) ao invés do E (&&) pois a senha estará inválida SE a quantidade for menor que 8 OU se ela for maior que 32. Isto é, em um caso ou em outro.

O operador lógico && exige que para a expressão ser considerada verdadeira ambos os casos verificados devem ser verdadeiros e, se olharmos bem, não tem como a quantidade de caracteres de um valor ser AO MESMO TEMPO menor que 8 e maior que 32 e assim, essa expressão nunca seria avaliada como verdadeira pois ela em si entra em contradição. Éh... esses operadores são meio confusos mesmo... :)

Peço que faça o teste e veja se ela atende ao que você espera e se entendi bem esses requisitos. Aqui testei as seguintes senhas:

Válidas:

  • Abcd1234
  • aBcD123567
  • 123456aBc

Inválidas:

  • abc12345 (não tem letra maiúscula)
  • ABCDE123 (não tem letra minúscula)
  • ADddeAeBGh (não tem número)
  • João12356b (tem acentuação)
  • Joao12356b$ (tem caractere especial)
  • ab12A (não tem a quantidade mínima exigida)

Espero ter ajudado e qualquer dúvida, estamos por aqui.

Att.

Muito obrigada!!!! Ajudou bastante! vou levar a dica do && pra vida, não tinha percebido esse erro.

eu de novo!!!! me veio uma outra dúvida, na verdade.

  • a respeito dos caracteres especiais, eu poderia colocar da forma que eu coloquei ou estaria errado?
  • não pode ter caractere de pontuação, acentuação ou espaço
  • fiz assim: (?=\S+$)[^@\.;\(\)\_!?&\-\+\^\´âêôáéíóúÂÊÔÁÉÍÓÚ]+$

vi que no código do instrutor não tem, mas gostaria muito de saber como ficaria essa parte

Oi,

Então... sim você pode verificar os caracteres como você fez, mas aí teria que ter muita atenção em não esquecer nenhum pois, por exemplo, pela regra da sua expressão regular passaria uma senha com "João" pois o caractere ~ não está sendo monitorado.

Por isso mesmo fiz uma regex mais enxuta dizendo que apenas caracteres entre A-Z, a-z e dígitos entre 0-9 serão aceitos. E no caso das letras, a expressão já não aceita caracteres acentuados.

Se reparar bem, no final do post que fiz com uma proposta de solução, uma das senhas que é considerada inválida é João12356b justamente por conta da acentuação.

Então, SIM, você pode fazer uma lista completa com todos os caracteres acentuados que ele deve verificar, mas se NENHUM caractere acentuado é aceito, então a gente simplesmente usa o [a-zA-Z0-9] que já atende.

O problema seria se alguns caracteres acentuados são aceitos e outros não! Aí sim, teríamos que fazer uma lista daqueles que são aceitos ou negados e deixar explícito na nossa expressão regular. Acredito que não seja o caso aqui.

É isso... espero, mais uma vez, ter ajudado!

\m/

Agora sim, tudo fico claro! Muito, muito obrigada mesmo! Estou contente em ter entendido :D