Regex para senha. Restringindo Caracteres Especiais

2

Estou tentando ter algumas entradas de senha nos modelos de formação em nuvem da AWS. E para restringir a senha para caracteres numéricos alfa e subconjunto de caracteres especiais. Eu tentei o seguinte:

"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#@$?]).{8,}$"

Isso informa que deve haver pelo menos uma letra maiúscula e minúscula junto com um dígito numérico. Além disso, restringe o conjunto de caracteres especiais para [#@$?]

O que eu observei foi que qualquer caractere especial, se fosse o último, era permitido. Em qualquer outro lugar, não foi permitido como esperado

Assim, Hello*E1 não é permitido, mas HelloE1* foi permitido.

Como desabilitar todos os caracteres especiais, exceto [#@$?] , não importa onde eles apareçam?

Além disso, como não permitir todo o conjunto de caracteres especiais? "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$ não ajudou. Isso permitiu todos os caracteres especiais.

Qualquer ajuda é apreciada.

    
por Prabhu 12.09.2017 / 21:46

3 respostas

3

Regex:

^(?=[a-zA-Z0-9#@$?]{8,}$)(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9]).*

Explicação:

Na regex que você forneceu, o lookaheads serve para garantir que sua string atenda a algumas condições específicas, mas elas não são o filtro real que mantém as strings indesejadas. Você especificou as seguintes condições:

  • (?=.*?[A-Z]) : corresponde a pelo menos uma letra maiúscula.
  • (?=.*?[a-z]) : corresponde a pelo menos uma letra minúscula.
  • (?=.*?[0-9]) : corresponde a pelo menos um número.
  • (?=.*?[#@$?]) : corresponde a pelo menos um desses caracteres: #@$?
  • .{8,} : corresponde a qualquer caractere pelo menos 8 vezes.

Mas há pelo menos duas falhas:

  • A parte (?=.*?[#@$?]) é desnecessária porque esses caracteres especiais são opcionais, não obrigatórios [1].

  • Como eu disse antes, você não especificou um filtro real, por isso, graças à .{8,} part, seu regex aceitará qualquer string, desde que atenda às condições estabelecidas pelas verificações iniciais, mesmo que tenha caracteres especiais indesejados [1].

Para resolver essas falhas, é necessário:

  • Exclua a parte (?=.*?[#@$?]) .

  • Adicione um novo lookahead que atue como o filtro mencionado acima.

Para construir esse filtro, você deve pensar em "quais caracteres eu quero permitir?" em vez de "quais caracteres eu quero proibir?", porque esse é um cenário mais fácil de lidar neste caso específico. Se você disser que só deseja que a-z , A-Z , 0-9 e #@$? sejam seus caracteres permitidos, a aparência inicial deve ficar assim:

(?=[a-zA-Z0-9#@$?])

Mas, nesta etapa, você pode até mesmo definir o tamanho mínimo e informar a parte inicial por onde começar e onde parar (o início e o fim da string nesse caso):

(?=[a-zA-Z0-9#@$?]{8,}$)

Eu omiti o ^ aqui porque ele já está no começo de tudo, então não é necessário ser redundante. Agora apenas reunimos todas as verificações e correspondemos a senha válida usando .* em vez de .{8,} :

^(?=[a-zA-Z0-9#@$?]{8,}$)(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9]).*

Nota:

  1. Embora, no regex e nos exemplos que você forneceu, eu realmente não sei o porquê: 1) #@$? não foram tratados como obrigatórios; 2) caracteres indesejados só eram permitidos no final da string e não em outro lugar. Talvez tenha algo a ver com o mecanismo de regex usado pela AWS, porque tudo funcionou como esperado quando eu testei por conta própria.
por 13.09.2017 / 05:57
3

Queremos uma lookahead ancorada no início da string para cada tipo de caractere requerido, bem como o requisito de comprimento. Em seguida, um simples .* para engolir tudo:

^(?=[0-9a-zA-Z#@\$\?]{8,}$)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9]).*

Explicação:

Primeiramente, decidi evitar o uso do quantificador lento ao corresponder os tipos de caracteres necessários (por exemplo, uma maiúscula) pelos seguintes motivos:

  • Eles são caros.
  • Diferentes mecanismos de regex têm diferentes formas de significar preguiça. (Um casal não suporta isso.)
  • Eles não são tão comuns / familiares quanto a alternativa.

Portanto, para eficiência, legibilidade e "portabilidade", estou usando a construção ^[^x]*[x] .

Agora, quebrando o resto ...

^ : tudo ancorado no início

(?=[0-9a-zA-Z#@\$\?]{8,}$) : olhar para frente com 8 ou mais caracteres permitidos entre o início e o fim da sequência.

Os próximos três usam o mesmo padrão: um lookahead correspondendo a zero ou mais de um char não correspondente a um caractere obrigatório, em seguida, ao caractere obrigatório. Estes são todos ancorados no começo, então o efeito é permitir uma correspondência do caractere necessário em qualquer posição na string:

(?=[^a-z]*[a-z]) : pelo menos uma minúscula.

(?=[^A-Z]*[A-Z]) : pelo menos uma maiúscula.

(?=[^0-9]*[0-9]) : pelo menos um dígito.

.* : Tudo acima é lookahead que não consome nada, então consuma tudo aqui. O primeiro lookahead garante que toda a string seja válida, por isso é seguro.

Eu não faço afirmações sobre isso ser otimizado (exceto para evitar o quantificador preguiçoso). Essa é simplesmente uma das formas mais fáceis de compreender.

Nota: a causa do problema que você observou com #@$? deve-se ao fato de o lookahead não estar ancorado no final da string. Qualquer qualquer personagem irá corresponder após um desses quatro (e não necessariamente apenas na última posição). Naturalmente, você não pode simplesmente adicionar $ , pois isso elimina os caracteres válidos. É por isso que incluo todos os caracteres válidos no mesmo lookahead.

    
por 13.09.2017 / 04:01
2

Seu regexp não proíbe nenhum caractere, apenas requer uma instância de cada classe. Para restringir os caracteres permitidos, altere seu . (o que significa qualquer personagem) para o conjunto de caracteres permitidos:

^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#@$?])[a-zA-Z0-9#@$?]{8,}$

Observe que, se você pretende usar uma string perl , precisará escapar de $ se @ s ou usar aspas strongs ( '...' ou q{...} ). Você também quer garantir que o regexp funcione no modo ASCII ( a-z corresponde apenas a letras inglesas e . corresponde a qualquer byte).

Remova o (?=.*?[#@$?]) se você não exigir pelo menos um desses símbolos.

    
por 13.09.2017 / 12:17