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:
- 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.