Programa de verificação de senha

3
Estou pondo minha cabeça nisso por um bom tempo. Este programa de verificação de senha garante que a senha fornecida inclua:

  • Letras maiúsculas e minúsculas
  • Pelo menos 10 dígitos
  • Pelo menos um número

O código funciona quase bem, com exceção de letras maiúsculas. Quando um único capital é inserido como a senha, o programa altera o valor de flagncap, enquanto não deveria. Alguém pode ajudar?

#!/bin/bash

echo "Please enter password: "
read user_passwd
flaglng=0
flagcap=0
flagncap=0
flagnum=0
if [[ ${#user_passwd} -ge 10 ]]; then
    flaglng=1
fi

if [[ "$user_passwd" = *[A-Z]* ]]; then
    flagcap=1
fi

if [[ "$user_passwd" = *[a-z]* ]]; then
    flagncap=1
fi

if [[ "$user_passwd" = *[0-9]* ]]; then
    flagnum=1
fi

if [[ "$flaglng" == 1 && "$flagcap" == 1 && "$flagncap" == 1 && "$flagnum" == 1 ]]; then
     echo "Password Strong!"
fi

if [[ "$flaglng" = 0 ]]; then
   echo "Weak Password! It should include at least 10 characters."
fi

if [[ "$flagcap" = 0 ]]; then
    echo "Weak Password! It should include at least 1 upper case letter."
fi

if [[ "$flagncap" = 0 ]]; then
    echo "Weak Password! It should include at least 1 lower case letter."
fi

if [[ "$flagnum" = 0 ]]; then
    echo "Weak Password! It should include at least 1 number."
fi
    
por Akis Tachmatzidis 15.11.2017 / 18:59

2 respostas

9

Sempre que você trabalha com intervalos de caracteres, é uma boa idéia inserir export LC_ALL=C (ou C.UTF-8 se você precisar de suporte para caracteres fora da faixa ASCII) no início do script, caso contrário, você pode se surpreender com o A-Z e a-z mean ...

Por exemplo:

$ unset LC_ALL
$ export LANG=en_US.UTF-8
$ [[ 'abc' = *[A-Z]* ]] && echo Match || echo No match
Match
$ export LC_ALL=C
$ [[ 'abc' = *[A-Z]* ]] && echo Match || echo No match
No match

O shell usa o intervalo [A-Z] para indicar todos os caracteres que classificam entre A e Z na localidade atual. No en_US locale b , classifica entre A e Z ; daí abc corresponde a *[A-Z]* . Por outro lado, no C locale b não classifica entre A e Z , porque os caracteres C locale são classificados estritamente de acordo com seu ponto de código.

    
por AlexP 15.11.2017 / 19:29
9

Primeiro, você não precisa de muitas ramificações if s. Como em tudo. Em vez disso, faça algo assim:

goodpassword=1

...

if [[ "$user_passwd" = *[A-Z]* ]]; then 
    echo "Weak Password! It should include at least 1 upper case letter."
    goodpassword=0
fi

...

if [[ "$goodpassword" = 1 ]]; then
    echo "Good password!"
fi

Para corrigir seu problema com os globs, use expressões regulares. Elimine o * e use ~ .

if [[ "$user_passwd" =~ [A-Z] ]]; then 
    flagcap=1
fi

Regexes em geral oferecem muito mais controle e capacidade com correspondência e verificação. Você pode, de fato, condensar esse script inteiro em uma única expressão regular, se quiser (embora você perca a verbosidade).

Amostra:

$ ./pwcheck.sh 
Please enter password : 
a
Weak Password! It should include at least 10 characters.
Weak Password! It should include at least 1 upper case letter.
Weak Password! It should include at least 1 number.

$ ./pwcheck.sh 
Please enter password : 
A
Weak Password! It should include at least 10 characters.
Weak Password! It should include at least 1 lower case letter.
Weak Password! It should include at least 1 number.
    
por Kaz Wolfe 15.11.2017 / 19:18

Tags